【问题标题】:Inserting table names and the number of records in T-SQL using cursor (Msg 207, Level 16, State 1, Line 1 Invalid column name 'table_x')使用游标在 T-SQL 中插入表名和记录数(Msg 207, Level 16, State 1, Line 1 Invalid column name 'table_x')
【发布时间】:2019-03-21 09:42:35
【问题描述】:

我收到来自特定供应商的数据(多个文件),我需要记录表名以及记录/表的数量。我尝试使用以下代码:

declare 
@TableName sysname,
@sqlstring nvarchar (1000);


DECLARE db_cursor CURSOR FOR 
SELECT Name 
FROM DataBase.dbo.Sysobjects 
WHERE name like '%SupplierName%' and crdate = '20190320';

if OBJECT_ID(N'tempdb..#Mytable') is not null
exec ('drop table #MyTable');

create table #MyTable (
    TableName varchar (100),
    Qty int);

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @tablename  


WHILE @@FETCH_STATUS = 0  
BEGIN  
  set @sqlstring = N'insert into #MyTable (TableName, Qty) select  cast(' + @Tablename + N' as varchar (100)), (select count(*) from DataBase.dbo.' + quotename(@Tablename) + N' as Qty)'  
  EXECUTE master.dbo.sp_executesql @sqlstring
  FETCH NEXT FROM db_cursor INTO @tablename 
END  

CLOSE db_cursor  
DEALLOCATE db_cursor

我收到如下错误消息:

消息 207,级别 16,状态 1,第 1 行无效的列名称“table_1”。

消息 207,级别 16,状态 1,行 1 列名“table_2”无效。 (...)

消息 207,级别 16,状态 1,第 1 行无效的列名称“table_n”。

这可能意味着游标正在获取表名,因此错误可能在我的动态 SQL 中,但我无法修复它。 我使用的是 MS Server 2012,是 SQL 的初学者。如有任何有用的提示指出我的错误,将不胜感激。

【问题讨论】:

    标签: sql-server sql-server-2012 dynamic-sql database-cursor


    【解决方案1】:

    您的动态 SQL 正在生成...

    select  cast(Tablename as varchar (100)), (select count(*) from DataBase.dbo.[Tablename]) as Qty)
    

    你需要

    select  cast('Tablename' as varchar (100)), (select count(*) from DataBase.dbo.[Tablename]) as Qty)
    

    你可以这样解决

    set @sqlstring = N'insert into #MyTable (TableName, Qty) select  cast(' + quotename(@Tablename, '''') + N' as varchar (100)), (select count(*) from DataBase.dbo.' + quotename(@Tablename) + N' as Qty)' 
    

    quootename(@Tablename, '''') 将添加缺少的引号以获取 'TableName' 作为值,而不是作为参考

    我会改变它,看起来更可读,但这是你的电话

    set @sqlstring = N'SELECT ' + QUOTENAME(@TableName, '''') + N',COUNT(1) 
        FROM DataBase.dbo.' + quotename(@Tablename) 
    INSERT #MyTable (TableName, Qty)
    EXECUTE sp_executesql @sqlstring
    FETCH NEXT FROM db_cursor INTO @tablename
    

    【讨论】:

    • 丹尼尔,非常感谢,这实际上解决了这个问题!我不知道“ quotename(@Tablename, '''') ”的这种用法,很好的提示!
    【解决方案2】:

    为什么你的陈述不符合以下原因:

    '...cast(' + @Tablename + N' as varchar (100))...'
    

    这将隐藏到 SQL 中

    CAST(YourTableName AS varchar(100))
    

    其中,您可能会看到没有意义。您希望 YourTableName 用单引号括起来,并且可能是 nvarchar。你可以通过这样做来实现:

        '...cast(N' + QUOTENAME(@Tablename,N'''') + N' as nvarchar (100))...'
    

    您可以更“轻松”地将其构建到单个语句中,而不是使用游标,并使用PRINT 进行故障排除。这应该符合您的目标,但我无法测试,因为我无权访问您的系统:

    CREATE TABLE #MyTable(TableName sysname,
                          Qty int);
    
    DECLARE @SQL nvarchar(MAX);
    
    SET @SQL = N'INSERT INTO #MyTable(TableName, Qty)' + NCHAR(13) + NCHAR(10) +
               STUFF((SELECT N'UNION ALL' + NCHAR(13) + NCHAR(10) +
                             N'SELECT N' + QUOTENAME([name],N'''') + N',' + NCHAR(13) + NCHAR(10) +
                             N'       (SELECT COUNT(*) FROM dbo.' + QUOTENAME([name]) + N')'
                      FROM sys.sysobjects  --I assume this should have been sys
                      WHERE [name] LIKE N'%SupplierName%'
                        AND crdate = '20190320'
                      FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,11,N'') + N';'
    --PRINT @SQL --Your debugging best friend
    EXEC sp_executesql @SQL;
    

    【讨论】:

    • 拉努,非常感谢!我使用了类似的方法来解决它,但它涉及到更多的手动更改脚本,这非常有用 - 我不知道以这种方式使用“东西”,这是另一个很好的提示。虽然我想检查为什么我的光标解决方案不起作用,因为这可能更适合我稍后必须处理这些数据的一些任务(我的意思是类似的方式)。我确实使用了 print @sql 我只是没有指出明显的,你,有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多