这应该是一件容易的事情,但它让我完全难过。
您可以使用oneliner手动轻松返回表格中每个字段的计数,如:
select count(FIELD1) from TABLE1 --42,706
select count(FIELD5) from TABLE1 --42,686
select count(FIELD9) from TABLE1 --2,918
如果您想以相同的方式查看几十个表格,这会很慢且很痛苦,并且需要您事先知道字段的名称。
有一个脚本可以连接到任何数据库,只需输入一个表名,它会自动返回该表的每个字段的计数吗?
似乎你可以完成一半的工作:
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'TABLE1'
即使我的准系统接近(明确地击中一个字段而不是全部字段),有些东西也存在缺陷:
declare @TABLENAME varchar(30), @FIELDNAME varchar(30)
set @TABLENAME = 'TABLE1'
set @FIELDNAME = (select top 1 COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = @TABLENAME
and COLUMN_NAME = 'FIELD9')
select @FIELDNAME, count(@FIELDNAME) from TABLE1
结果是42,706。回想一下上面的例子,FIELD9只包含2,918个值。
即使这不是问题,更动态的查询会将最后一行替换为:
select @FIELDNAME, count(@FIELDNAME) from @TABLENAME
但SQL Server返回:
Must declare the table variable "@TABLENAME".
所以我可以通过使用临时表重构查询来避免这种情况:
declare @FIELDNAME varchar(30)
set @FIELDNAME = (select top 1 COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'TABLE1'
and COLUMN_NAME = 'FIELD9')
if OBJECT_ID('TEMPDB..#TEMP1') is not null
drop table #TEMP1
select *
into #TEMP1
from TABLE1 --still not exactly dynamic!
select @FIELDNAME, count(@FIELDNAME) from #TEMP1
但这仍然让我们回到原来的问题,即返回42,706而不是2,918。
我正在运行SQL Server 2008 R2,如果它有任何区别。
答案 0 :(得分:2)
您的查询:
SELECT @FIELDNAME, COUNT(@FIELDNAME) FROM TABLE1
不计算FIELD9
,@FIELDNAME
被视为常量。这就像做COUNT(*)
。
你应该使用动态sql:
DECLARE @sql VARCHAR(MAX)
SET @sql = 'SELECT ''' + @fieldName + ''', COUNT([' + @fieldName + ']) FROM [' + @tableName + ']'
EXEC(@sql)
要获取所有列并将其返回到单个结果集中,而不使用Temporary Table
和CURSOR
:
DECLARE @sql NVARCHAR(MAX) = ''
SELECT @sql = @sql +
'SELECT ''' + COLUMN_NAME + ''' AS ColName, COUNT([' + COLUMN_NAME + ']) FROM [' + @tableName + ']' + CHAR(10) +
'UNION ALL' + CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @tableName
SELECT @sql = LEFT(@sql, LEN(@sql) - 10)
EXEC(@sql)
答案 1 :(得分:0)
设置@TargetTableName即可完成工作
DECLARE @TargetTableName sysname = '*'
SET NOCOUNT ON
DECLARE @TableName sysname, @ColumnName sysname, @Sql nvarchar(max)
DECLARE @TableAndColumn table
(
TableName sysname,
ColumnName sysname
)
DECLARE @Result table
(
TableName sysname,
ColumnName sysname,
NonNullRecords int
)
INSERT @TableAndColumn
SELECT o.name, c.name FROM sys.objects o INNER JOIN sys.columns c ON o.object_id = c.object_id
WHERE (o.name = @TargetTableName OR @TargetTableName = '*') AND o.type = 'U' AND c.system_type_id NOT IN (34, 35, 99) -- 34:image 35:text 99:ntext
ORDER BY c.column_id
DECLARE column_cursor CURSOR FOR SELECT TableName, ColumnName FROM @TableAndColumn
OPEN column_cursor
FETCH NEXT FROM column_cursor
INTO @TableName, @ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @Sql = 'SELECT ''' + @TableName + ''' AS TableName, ''' + @ColumnName + ''' AS ColumnName, COUNT([' + @ColumnName + ']) AS NonNullRecords FROM [' + @TableName + ']'
print @Sql
INSERT @Result
EXEC (@Sql)
FETCH NEXT FROM column_cursor
INTO @TableName, @ColumnName
END
CLOSE column_cursor;
DEALLOCATE column_cursor;
SET NOCOUNT OFF
SELECT * FROM @Result