我一直在尝试使用动态名称创建表时遇到问题。我一直收到这些错误:
消息102,级别15,状态1,过程SP_SearchTables,第159行
'@tablename'附近的语法不正确。消息1087,等级15,状态2,程序SP_SearchTables,第165行
必须声明表变量“@tablename”。Msg 1087,Level 15,State 2,Procedure SP_SearchTables,Line 171
必须声明表变量“@tablename”。
正如您在存储过程中看到的那样,在此更改之前,我有SearchTMP
而不是@tablename
,但我不想给出固定名称,我想提供动态名称。考虑到这一点,我给了一个名字和一些随机数字,但它一直给我以前显示的错误,你能帮助我吗?
我将发布我的存储过程。
ALTER PROCEDURE [dbo].[SearchTables]
@SearchStr NVARCHAR(60),
@GenerateSQLOnly BIT = 0,
@SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE @MatchFound BIT
SELECT @MatchFound = 0
DECLARE @CheckTableNames TABLE (Schemaname sysname, Tablename sysname)
DECLARE @SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE @SQLTbl TABLE
(
Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT
)
DECLARE @SQL VARCHAR(MAX)
DECLARE @TableParamSQL VARCHAR(MAX)
DECLARE @SchemaParamSQL VARCHAR(MAX)
DECLARE @TblSQL VARCHAR(MAX)
DECLARE @tmpTblname sysname
DECLARE @ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(@SchemaNames)) =''
BEGIN
SELECT @SchemaNames = '%'
END
IF CHARINDEX(',',@SchemaNames) > 0
SELECT @SchemaParamSQL = 'SELECT ''' + REPLACE(@SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT @SchemaParamSQL = 'SELECT ''' + @SchemaNames + ''' as SchemaName '
SELECT @TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et ON (et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO @CheckTableNames (Schemaname, Tablename)
EXEC (@TblSQL)
IF NOT EXISTS(SELECT 1 FROM @CheckTableNames)
BEGIN
SELECT @ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT @ErrMsg
RETURN
END
IF LTRIM(RTRIM(@SearchStr)) =''
BEGIN
SELECT @ErrMsg = 'Please specify the search string in @SearchStr Parameter'
PRINT @ErrMsg
RETURN
END
ELSE
BEGIN
SELECT @SearchStr = REPLACE(@SearchStr,',,,',',#DOUBLECOMMA#')
SELECT @SearchStr = REPLACE(@SearchStr,',,','#DOUBLECOMMA#')
SELECT @SearchStr = REPLACE(@SearchStr,'''','''''')
SELECT @SQL = 'SELECT ''' + REPLACE(@SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO @SearchStringTbl (SearchString)
EXEC(@SQL)
UPDATE @SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO @SQLTbl (Tablename, WHEREClause)
SELECT
QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN @SearchStringTbl SearchSTR
WHERE STY.name IN ('varchar', 'char', 'nvarchar', 'nchar', 'text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM
SYS.tables ST
JOIN
@CheckTableNames chktbls ON chktbls.Tablename = ST.name
JOIN
SYS.schemas SCh ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE
ST.name <> 'SearchTMP'
GROUP BY
ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
DECLARE @numbers VARCHAR(MAX)
SET @numbers = CONVERT(NUMERIC(12, 0), RAND() * 899999999999) + 100000000000
DECLARE @tablename VARCHAR(MAX)
SET @tablename = 'SearchTMP' + @numbers
UPDATE @SQLTbl
SET SQLStatement = N'SELECT * INTO ' + @tablename +' FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM @SQLTbl
WHERE WHEREClause IS NULL
DECLARE @output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM @SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 @tmpTblname = Tablename , @SQL = SQLStatement
FROM @SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF @GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('@tablename','U') IS NOT NULL
DROP TABLE @tablename
EXEC (@SQL)
IF EXISTS(SELECT 1 FROM @tablename)
BEGIN
--SELECT parsename(@tmpTblname,1) FROM SearchTMP
SELECT @MatchFound = 1
INSERT INTO @output (Id, Name)
SELECT *
FROM [DynaForms].[dbo].[Enums_Tables]
WHERE id IN (SELECT parsename(@tmpTblname, 1) FROM @tablename)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT @tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(@SQL,'INTO @tablename','')
END
UPDATE @SQLTbl
SET Execstatus = 1
WHERE Tablename = @tmpTblname
END
SELECT * FROM @output
--Select * from @SQLTbl
IF @MatchFound = 0
BEGIN
SELECT @ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT @ErrMsg
RETURN
END
SET NOCOUNT OFF
修改
我更改了我的存储过程以获得动态sql,但它给了我这个错误:
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'.
我认为这个问题出在我的子查询中,但是我看不到它的工作原理,请你帮忙吗?子查询在这里:
DECLARE @SQLSUBQUERY VARCHAR(max);
SELECT @SQLSUBQUERY = 'SELECT * FROM [DynaForms].[dbo].[Enums_Tables] ';
SELECT @SQLSUBQUERY = @SQLSUBQUERY + 'WHERE id IN (SELECT parsename(@tmpTblname,1) FROM @tablename)';
INSERT INTO @output (Id, Name)
EXEC sp_executesql @SQLSUBQUERY
完整代码:
ALTER PROCEDURE [dbo].[SP_SearchTables]
@SearchStr NVARCHAR(60),
@GenerateSQLOnly Bit = 0,
@SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE @MatchFound BIT
SELECT @MatchFound = 0
DECLARE @CheckTableNames TABLE (Schemaname sysname, Tablename sysname)
DECLARE @SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE @SQLTbl TABLE (Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT)
DECLARE @SQL VARCHAR(MAX)
DECLARE @TableParamSQL VARCHAR(MAX)
DECLARE @SchemaParamSQL VARCHAR(MAX)
DECLARE @TblSQL VARCHAR(MAX)
DECLARE @tmpTblname sysname
DECLARE @ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(@SchemaNames)) =''
BEGIN
SELECT @SchemaNames = '%'
END
IF CHARINDEX(',',@SchemaNames) > 0
SELECT @SchemaParamSQL = 'SELECT ''' + REPLACE(@SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT @SchemaParamSQL = 'SELECT ''' + @SchemaNames + ''' as SchemaName '
SELECT @TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO @CheckTableNames (Schemaname, Tablename)
EXEC(@TblSQL)
IF NOT EXISTS(SELECT 1 FROM @CheckTableNames)
BEGIN
SELECT @ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT @ErrMsg
RETURN
END
IF LTRIM(RTRIM(@SearchStr)) =''
BEGIN
SELECT @ErrMsg = 'Please specify the search string in @SearchStr Parameter'
PRINT @ErrMsg
RETURN
END
ELSE
BEGIN
SELECT @SearchStr = REPLACE(@SearchStr,',,,',',#DOUBLECOMMA#')
SELECT @SearchStr = REPLACE(@SearchStr,',,','#DOUBLECOMMA#')
SELECT @SearchStr = REPLACE(@SearchStr,'''','''''')
SELECT @SQL = 'SELECT ''' + REPLACE(@SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO @SearchStringTbl
(SearchString)
EXEC(@SQL)
UPDATE @SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO @SQLTbl (Tablename, WHEREClause)
SELECT
QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN @SearchStringTbl SearchSTR
WHERE
STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN @CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> 'SearchTMP'
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
declare @numbers varchar(MAx)
set @numbers = convert(numeric(12,0),rand() * 899999999999) + 100000000000
declare @tablename varchar(MAX)
set @tablename = 'SearchTMP' + @numbers
UPDATE @SQLTbl
SET SQLStatement = N'SELECT * INTO ' + @tablename +' FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM @SQLTbl
WHERE WHEREClause IS NULL
DECLARE @output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM @SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 @tmpTblname = Tablename , @SQL = SQLStatement
FROM @SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF @GenerateSQLOnly = 0
BEGIN
DECLARE @SQLs NVARCHAR(MAX)
SELECT @SQLs = 'DROP TABLE dbo.' + QUOTENAME(@tablename) + '';
IF OBJECT_ID(''+@tablename+'','U') IS NOT NULL
EXEC sp_executesql @SQLs;
EXEC (@SQL)
--IF EXISTS(SELECT 1 FROM @tablename)
BEGIN
--SELECT parsename(@tmpTblname,1) FROM SearchTMP
SELECT @MatchFound = 1
DECLARE @SQLSUBQUERY VARCHAR(max);
SELECT @SQLSUBQUERY = 'SELECT * FROM [DynaForms].[dbo].[Enums_Tables] ';
SELECT @SQLSUBQUERY = @SQLSUBQUERY + 'WHERE id IN (SELECT parsename(@tmpTblname,1) FROM @tablename)';
INSERT INTO @output (Id, Name)
EXEC sp_executesql @SQLSUBQUERY
--Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(@tmpTblname,1) FROM @tablename)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT @tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(@SQL,'INTO @tablename','')
END
UPDATE @SQLTbl
SET Execstatus = 1
WHERE Tablename = @tmpTblname
END
SELECT * FROM @output
--Select * from @SQLTbl
IF @MatchFound = 0
BEGIN
SELECT @ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT @ErrMsg
RETURN
END
SET NOCOUNT OFF
答案 0 :(得分:1)
至少存在以下错误:
如果OBJECT_ID('@ tablename','U')不是空
这是错误的,因为检查名称为@tablename
的表IF EXISTS(SELECT 1 FROM @tablename)
这会产生你所得到的错误。
DROP TABLE
不接受变量,使用动态sql到你的drop