使用游标在 T-SQL 中插入 table 名称和记录数(消息 207,级别 16,状态 1,第 1 行无效列名称 'table_x')

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')

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

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

我收到如下错误信息:

Msg 207, Level 16, State 1, Line 1 Invalid column name 'table_1'.

Msg 207, Level 16, State 1, Line 1 Invalid column name 'table_2'. (...)

Msg 207, Level 16, State 1, Line 1 Invalid column name 'table_n'.

这可能意味着光标正在获取 table 名称,因此错误可能出在我的动态 SQL 中,但我无法修复它。 我使用 MS Server 2012,是 SQL 的一个相对初级的用户。如有任何有用的提示指出我的错误,将不胜感激。

您的动态 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

为什么您的声明不符合以下原因:

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

这会隐藏到 SQL

CAST(YourTableName AS varchar(100))

其中,您可能会发现没有意义。您希望 YourTableName 包含在单引号中,并且可能作为 nvarchar。你可以通过这样做来实现:

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

您可以 "easily" 将其构建到单个语句中,然后使用 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;