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

Limit SQL query to only scan tables with less than 500 records

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

然而,这是一项非常耗时的任务,因此我希望将其限制为仅遍历包含 500 条或更少记录的 tables,并跳过充满无关紧要的大 tables无论如何数据。

我在弄清楚如何将我的 COUNT 包含在 table 中时遇到问题,因为我正在使用 varchar(256) 作为 table 名称。

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

如有任何帮助或建议,我们将不胜感激?

您需要做的就是计算 table 的计数并应用

这样的条件
if(select count(*) from table_name)<500
begin
    execute your query
end

您可以使用系统 table sys.dm_db_partition_stats 查找具有 500 多条记录的 table。

/* 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% 的准确性,否则它应该符合您的目的。我针对十亿条记录加数据库测试了查询,发现所有行计数都与基础 tables 完全匹配。有关详细信息,请参阅 docs

您可以使用 sys.dm_db_partition_stats table 的近似方法。只需按照此代码添加 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?