限制SQL查询仅扫描少于500条记录的表

时间:2016-11-09 09:04:18

标签: sql sql-server ssms

我创建了以下脚本,该脚本遍历数据库的所有字段中的所有值。

然而,这是一项非常耗时的任务,因此我希望将其限制为仅浏览具有500或更少记录的表,并跳过充满无关数据的大表。

我有问题弄清楚如何在表格中包含我的COUNT,因为我正在使用varchar(256)作为表名。

USE [Name of Database]
DECLARE @SearchStr nvarchar(100) = 'Text to search fields for'
DECLARE @Results TABLE (ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET  @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL

BEGIN
    SET @ColumnName = ''
    SET @TableName = 
    (
        SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM     INFORMATION_SCHEMA.TABLES
        WHERE         TABLE_TYPE = 'BASE TABLE'
            AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            AND    OBJECTPROPERTY(
                    OBJECT_ID(
                        QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                         ), 'IsMSShipped'
                           ) = 0
    )

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)

    BEGIN
        SET @ColumnName =
        (
            SELECT MIN(QUOTENAME(COLUMN_NAME))
            FROM     INFORMATION_SCHEMA.COLUMNS
            WHERE         TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                AND    TABLE_NAME    = PARSENAME(@TableName, 1)
                AND    DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal')
                AND    QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @ColumnName IS NOT NULL

        BEGIN
            INSERT INTO @Results
            EXEC
            (
                'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                FROM ' + @TableName + ' (NOLOCK) ' +
                ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
            )
        END
    END    
END

SELECT ColumnName, ColumnValue FROM @Results

我们将非常感谢您提供任何帮助或建议吗?

3 个答案:

答案 0 :(得分:1)

您可以使用sys.dm_db_partition_stats表格的近似方式。只需在此代码中添加JOIN:

    ...
    SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM     INFORMATION_SCHEMA.TABLES

            --add this JOIN 
            JOIN 
              (
                SELECT
                   object_name(object_id) as Table_Name
                FROM sys.dm_db_partition_stats
                WHERE (index_id < 2)
                GROUP BY object_name(object_id)
                HAVING SUM(row_count)<=500
              ) as Stat
             ON  INFORMATION_SCHEMA.TABLES.TABLE_NAME = Stat.Table_Name
             -- add this JOIN 


             WHERE         TABLE_TYPE = 'BASE TABLE'
                AND    QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND    OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )
    ...

更多细节: Fastest way to count exact number of rows in a very large table?

答案 1 :(得分:0)

您需要做的就是计算一个表的计数,并在条件如

时应用
if(select count(*) from table_name)<500
begin
    execute your query
end

答案 2 :(得分:0)

您可以使用系统表sys.dm_db_partition_stats查找包含500多条记录的表。

/* Returns tables with 500+ rows, 
 * using the system tables.
 */
SELECT
    s.name,
    o.name,
    st.row_count
FROM    
    sys.objects AS o
        INNER JOIN sys.schemas AS s                 ON s.schema_id  = o.schema_id
        INNER JOIN sys.dm_db_partition_stats st     ON st.object_id = o.object_id

WHERE
    o.type = 'U'                -- User defined is a table.     
    AND st.index_id IN (0, 1)   -- 0 = Heap, 1 = Clustered index.
    AND st.row_count > 500
ORDER BY 
    st.row_count DESC
;

返回的行数是近似值。除非您需要100%的准确度,否则它应该满足您的目的。我针对十亿条记录加数据库测试了查询,发现所有行计数与基础表完全匹配。有关详情,请参阅docs