Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在表循环中创建列循环以计算数据库中所有字段的填充率_Sql_Sql Server_Loops_Fill_Rate - Fatal编程技术网

Sql 在表循环中创建列循环以计算数据库中所有字段的填充率

Sql 在表循环中创建列循环以计算数据库中所有字段的填充率,sql,sql-server,loops,fill,rate,Sql,Sql Server,Loops,Fill,Rate,我有两个数据库,超过400个表,我必须计算填充率。我有一个循环用于计算表中所有列的填充率,但如何才能对数据库中的所有表执行此操作??请帮忙! 我正在使用SQL Server 下面是循环表中所有列以计算填充率的代码- DECLARE @Table NVARCHAR(max) = 'dbo.[TableName]' ,@MetaTable NVARCHAR(128) = '#TempTable' ,@ColumnName NVARCHAR(128) ,@Iterator INT =

我有两个数据库,超过400个表,我必须计算填充率。我有一个循环用于计算表中所有列的填充率,但如何才能对数据库中的所有表执行此操作??请帮忙! 我正在使用SQL Server

下面是循环表中所有列以计算填充率的代码-

DECLARE @Table NVARCHAR(max) = 'dbo.[TableName]'
   ,@MetaTable NVARCHAR(128) = '#TempTable'
   ,@ColumnName NVARCHAR(128)
   ,@Iterator INT = 1
   ,@SQL1 NVARCHAR(MAX)

SELECT c.NAME
  ,c.COLUMN_ID
  ,ROW_NUMBER() OVER (ORDER BY COLUMN_ID) AS RN
INTO #Cols
FROM SYS.COLUMNS c
WHERE c.OBJECT_ID = OBJECT_ID(@Table);

WHILE @Iterator <= (SELECT ISNULL(MAX(RN),0) FROM #Cols)
BEGIN
    SET @ColumnName = (SELECT NAME FROM #Cols WHERE RN = @Iterator)
     SET @SQL1 =  'INSERT INTO ' + @MetaTable + ' (Table_Name, Column_Name, 
                   Fill_Rate) '
              + 'SELECT ''' + REPLACE(@Table,'DBO.','') + ''', ''' + 
      @ColumnName + ''', 100 * CONVERT(DECIMAL(8,3), SUM(CASE WHEN [' + 
      @ColumnName + '] IS NULL THEN 0 ELSE 1 END)) / COUNT(1) AS [' + 
      @ColumnName + '_fill]' + ' FROM ' + @Table

    EXEC sp_executesql @SQL1
    SET @Iterator += 1
    END

我建议使用光标来完成这个简洁的小任务:

CREATE TABLE #MetaTable (
  TABLE_SCHEMA sysname,
  TABLE_NAME sysname,
  COLUMN_NAME sysname,
  fill_rate float NULL);

DECLARE 
  @schema sysname,
  @table sysname,
  @column sysname,
  @sql nvarchar(max);

DECLARE column_cusor CURSOR FAST_FORWARD FOR
  SELECT s.name, t.name, c.name
    FROM sys.schemas s
      INNER JOIN sys.tables t ON s.schema_id = t.schema_id
        INNER JOIN sys.columns c ON t.object_id = c.object_id;

OPEN column_cusor;
FETCH NEXT FROM column_cusor INTO @schema, @table, @column;

WHILE @@FETCH_STATUS = 0
BEGIN

  SET @sql = 'SELECT ' +  QUOTENAME(@schema, '''') 
    + ', ' + QUOTENAME(@table, '''') 
    + ', ' + QUOTENAME(@column, '''') 
    + ', ' + '100.0 * SUM(CASE WHEN ' + QUOTENAME(@column)
      + ' IS NULL THEN 0 ELSE 1 END) /'
      + ' CASE WHEN COUNT(*) = 0 THEN 1 ELSE COUNT(*) END' 
    + ' FROM ' + QUOTENAME(@schema) + '.' + QUOTENAME(@table);

  INSERT INTO #MetaTable (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, fill_rate)
  EXEC (@sql);

  FETCH NEXT FROM column_cusor INTO @schema, @table, @column;
END

CLOSE column_cusor;
DEALLOCATE column_cusor;

SELECT * FROM #MetaTable;

您使用的是哪种数据库管理系统?该代码是特定于产品的。不建议SQL Server管理人员直接研究系统表,它们可能会在下一个SQL Server版本中更改。取而代之的是,在模式视图中使用信息。对于列,使用信息\u SCHEMA.columns;对于表,使用信息\u SCHEMA.tables。COLUMNview还包含一个序号位置,因此您不需要为它们指定行号。@WolfgangKai的信息架构视图并不总是准确的,也不总是包含所有信息。好奇您在哪里听说不应该使用sys.columns或sys.tables。至于列的顺序位置,它在sys.columns column_id中。@SeanLange我在担任MCT的10年多时间里一直不向学生使用系统表,正如Microsoft官方课件my bad中所述,我没有注意到OP中的sys.columns是目录视图。当然,您是对的,这些也可以使用,并且脚本将在未来的MSSQL版本中兼容,但是在这个问题上,我认为除了名称的长度之外,与信息模式视图相比没有任何优势。在我们的案例中,不需要博客文章中提到的所有详细数据。无论如何,感谢您的链接,非常感谢!:-虽然我很鄙视游标,但它在这里几乎是必需的……而且在那里是嵌套的。啊!!!稍微调整一下,如果表中没有行,就会得到一个被零除的错误+1如果他们使用不推荐的数据类型,那么他们也必须发挥创造性,因为ntext之类的东西对于计数是无效的。根据游标,我也是如此…:再次感谢,好的观点,OP应该定义如何处理没有记录的表。我认为它们是100%填充的,因为不存在的行中有一个空值。另一方面不存在的行包含一个值,因此所有不存在的行都是空的…@SeanLange Yes,Yes,Yes。至少对于ntext等,OP使用了全世界都称之为条件聚合的方法,我认为这也适用于ntext、文本和图像。如果它使用大小写表达式和sum aka条件聚合,则可以避免此问题