无效的对象名称 - #temptable

时间:2018-01-02 12:10:54

标签: sql-server stored-procedures

当我进行select * into时,此存储过程在数据库中创建一个表,因此,当有多个用户时,会出现错误并显示SearchTMP table already exists,即使我生成也会发生这种情况那桌子一滴。所以我决定制作一个临时表,如下面的代码所示:

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 <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' +  QUOTENAME(ST.NAME);

UPDATE @SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)

由于我之前不想声明或创建表,因此将在select * into中创建临时表。但是当我尝试通过填充参数来运行该程序时,它说:

>Msg 208, Level 16, State 0, Procedure SP_SearchTables_TEST, Line 265, Invalid object name #MyTempTable

整个存储过程:

ALTER PROCEDURE [dbo].[SearchTables_TEST]  @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 <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' +  QUOTENAME(ST.NAME);    

UPDATE @SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable 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('#MyTempTable','U') IS NOT NULL -- this line was uncomment
         DROP TABLE #MyTempTable   -- this line was uncomment


        EXEC (@SQL)      


        IF EXISTS(SELECT 1 FROM #MyTempTable) -- It was like this: SearchTMP
        BEGIN 
            SELECT @MatchFound = 1 

            INSERT INTO @output (Id, Name)
            Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(@tmpTblname,1) FROM #MyTempTable) -- It was like this: SearchTMP
        END 

     END 
     ELSE 
     BEGIN 
         PRINT REPLICATE('-',100) 
         PRINT @tmpTblname 
         PRINT REPLICATE('-',100) 
         PRINT replace(@SQL,'INTO #MyTempTable','') 
     END 

     UPDATE @SQLTbl 
        SET Execstatus = 1 
      WHERE Tablename = @tmpTblname 

END 

SELECT * FROM @output

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 

2 个答案:

答案 0 :(得分:3)

好的,所以快速测试实际上回答了这一点,我无法相信我错过了(/ facepalm)。你不能在动态SQL和临时表中使用INTO子句,然后引用它;你需要CREATE表。请考虑以下事项:

DECLARE @SQL varchar(max);

SET @SQL = 'SELECT 1 AS A, 2 AS B INTO #test;';
EXEC (@SQL);
SELECT *
FROM #test;
DROP TABLE #test;

这将返回错误:

  

Msg 208,Level 16,State 0,Line 5

     

无效的对象名称&#39; #test&#39;。

现在,以正确的方式:

DECLARE @SQL varchar(max);

CREATE TABLE #test (A int, B int);

SET @SQL = 'INSERT INTO #test SELECT 1 AS A, 2 AS B';
EXEC (@SQL);
SELECT *
FROM #test;
DROP TABLE #test;

这很好用。因此,您需要CREATE临时表,而不是使用INTO子句。

答案 1 :(得分:0)

而不是

Object_Id('#MyTempTable','U')

您需要使用

Object_Id('tempdb..#MyTempTable','U')

获取临时表的object_id以检查它是否存在。

临时表在TempDB系统数据库中创建