从information_schema插入表变量似乎什么都不检索

时间:2015-12-16 17:39:21

标签: sql-server sql-server-2008 tsql

SQL Server 2008.

我正在编写一些T-SQL来获取两个数据库之间通用的表列表(基本上是同一数据库的两个副本,因此列名是常见的),截断目标数据库中列表中的每个表并附加来自源数据库中匹配表的行。

作为其中的一部分,我正在构建一个列名列表,以便在最终的SELECT语句中使用它来执行追加。

问题在于,当我尝试将有问题的表的列名列表插入表变量时,我什么也得不到。然而,我分别开发了T-SQL的那一部分,并且它可以单独工作。

有什么明显的错误吗?

DECLARE @SourceCompany  CHAR(1)
DECLARE @TargetCompany  CHAR(1) 
DECLARE @SQL            NVARCHAR(4000)
DECLARE @lcParmDef      NVARCHAR(4000)
DECLARE @TableCount     INT
DECLARE @t              INT
DECLARE @ThisTable      NVARCHAR(256)
DECLARE @TableList      TABLE (name NVARCHAR(256), RowID INT)
DECLARE @ColumnCount    INT
DECLARE @c              INT
DECLARE @RowList        NVARCHAR(4000)
DECLARE @ThisCol        NVARCHAR(4000)
DECLARE @ColumnList     TABLE (column_name NVARCHAR(4000), id INT IDENTITY )
DECLARE @ColString      NVARCHAR(4000)

 ---------------- Set source and target companies here ----------------
SET @SourceCompany = 'Z'
SET @TargetCompany = 'X'
 ---------------- Set source and target companies here ----------------

INSERT @TableList (name, RowID) VALUES (N'stran',1), (N'sanal', 2)
SET @TableCount = @@ROWCOUNT
SET @t = 1

WHILE (@t <= @TableCount)

    BEGIN

        SELECT @ThisTable = name FROM @TableList WHERE RowID = @t
        SET @ThisTable = N'[dbo].[' + @ThisTable + N']'

         -- Clear target table.
        SET @SQL = N'TRUNCATE TABLE [COMP_' + @TargetCompany + N'].[dbo].[' + @ThisTable + N']'
        SET @lcParmDef = N''
        EXECUTE sp_executesql @SQL, @lcParmDef

        -- Build column list for current table.
        DELETE FROM @ColumnList
        INSERT INTO @ColumnList  
            SELECT column_name from information_schema.columns
            WHERE table_name = @ThisTable 

        -- PROBLEM - this always returns zero.
        SELECT @ColumnCount = Count(*) FROM @ColumnList

        SET @c = 1
        SET @ColString = ''
        WHILE (@c <= @ColumnCount)
            BEGIN
                SELECT @ThisCol = column_name FROM @ColumnList WHERE id = @c
                SET @ColString = @ColString + '[' + @ThisCol + ']'
                IF (@c < @ColumnCount) SET @ColString = @ColString + ','
                SET @c = @c + 1
            END

        --- Just print the column string for now, ultimately I will build a SELECT statement and execute.
        PRINT @ColString

        SET @t = @t + 1

    END

2 个答案:

答案 0 :(得分:1)

尝试以下更改

  1. 评论此行SET @ThisTable = N'[dbo].[' + @ThisTable + N']'。因为在information_schema.columns系统视图中,表名称将仅存储为tablename,而不是[dbo].[tablename]。甚至不是[square brackets]

  2. 为架构添加新的variable并为其指定dbo

  3. 声明@schema_name变量

     Declare @schema_name char(3) = 'dbo'
    
    1. 更改像这样插入查询。
    2. 将架构名称过滤器添加到查询

      INSERT INTO @ColumnList  
      SELECT column_name 
      from information_schema.columns
      WHERE table_name = @ThisTable
        and schema_name = @schema_name
      

答案 1 :(得分:0)

好的,事实证明使用'information_schema'需要数据库上下文。这里我使用变量中保存的动态数据库名称,你不能(AFAIK,烦人地)在sp_executesql语句中使用变量。所以我在下面做的是构建一些T-SQL并使用带有输出参数的-- Takes a list of tables in @TableList, truncates that table in a target database and appends all rows -- from the same table in a source database, building a column list dynamically in each case. DECLARE @SourceCo CHAR(1) DECLARE @TargetCo CHAR(1) DECLARE @SourceCoName CHAR(6) DECLARE @TargetCoName CHAR(6) DECLARE @SQLString NVARCHAR(4000) DECLARE @ParmDefinition NVARCHAR(4000) DECLARE @TableCount INT DECLARE @t INT DECLARE @ThisTable NVARCHAR(256) DECLARE @TableList TABLE (name NVARCHAR(256), RowID INT) DECLARE @RowList NVARCHAR(4000) DECLARE @ThisCol NVARCHAR(4000) DECLARE @ColumnList TABLE (column_name NVARCHAR(4000), id INT IDENTITY ) DECLARE @ColumnString NVARCHAR(4000) ---------------- Set source and target companies here ---------------- SET @SourceCo = 'Z' SET @TargetCo = 'X' SET @SourceCoName = 'COMP_' + @SourceCo SET @TargetCoName = 'COMP_' + @TargetCo ---------------- Set source and target companies here ---------------- -- Build the list of tables to process. INSERT @TableList (name, RowID) VALUES (N'stran',1), (N'sanal', 2) SET @TableCount = @@ROWCOUNT SET @t = 1 -- Iterate through list of tables. WHILE (@t <= @TableCount) BEGIN SELECT @ThisTable = name FROM @TableList WHERE RowID = @t -- Clear relevant table in target database. SET @SQLString = N'TRUNCATE TABLE [' + @TargetCoName + N'].[dbo].[' + @ThisTable + N']' SET @ParmDefinition = N'' EXECUTE sp_executesql @SQLString, @ParmDefinition -- Retrieve the column list for current table. SET QUOTED_IDENTIFIER OFF SET @SQLString = "DECLARE @ColumnList TABLE (column_name NVARCHAR(4000), id INT IDENTITY );" SET @SQLString = @SQLString + "DECLARE @c INT;" SET @SQLString = @SQLString + "DECLARE @ColumnCount INT;" SET @SQLString = @SQLString + "DECLARE @ThisCol NVARCHAR(4000);" SET @SQLString = @SQLString + "USE " + @SourceCoName + ";" SET @SQLString = @SQLString + "INSERT INTO @ColumnList SELECT column_name from information_schema.COLUMNS" SET @SQLString = @SQLString + " WHERE TABLE_NAME = '" + @ThisTable + "' " SET @SQLString = @SQLString + " AND TABLE_SCHEMA = 'dbo';" SET @SQLString = @SQLString + "SELECT @ColumnCount = Count(*) FROM @ColumnList;" SET @SQLString = @SQLString + "SET @c = 1; SET @ColStringOUT = '';" SET @SQLString = @SQLString + "WHILE (@c <= @ColumnCount) " SET @SQLString = @SQLString + " BEGIN " SET @SQLString = @SQLString + " SELECT @ThisCol = column_name FROM @ColumnList WHERE id = @c" SET @SQLString = @SQLString + " SET @ColStringOUT = @ColStringOUT + '[' + @ThisCol + ']'" SET @SQLString = @SQLString + " IF (@c < @ColumnCount) SET @ColStringOUT = @ColStringOUT + ','" SET @SQLString = @SQLString + " SET @c = @c + 1 " SET @SQLString = @SQLString + " END" SET QUOTED_IDENTIFIER ON SET @ParmDefinition = N'@ColStringOUT NVARCHAR(4000) OUTPUT' EXECUTE sp_executesql @SQLString, @ParmDefinition, @ColStringOUT = @ColumnString OUTPUT --- Just print the column string for now, ultimately I will build a SELECT statement using it. PRINT @ColumnString SET @t = @t + 1 END 动态执行它,以返回一个字符串,其中包含正在处理的每个表的列名。

REM INSERTING into database1."Users"
 SET DEFINE OFF;
Insert into database1."Users" ("id","right") values ('1','R');