动态 SQL 从 information_schema 获取行

发布于 2025-01-12 16:12:10 字数 908 浏览 0 评论 0原文

假设我正在数据库中查找特定列,所以我有类似的内容

SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME like ‘%employeeid%’

但我也想知道每个表有多少行,有人告诉我可以使用动态 SQL 来完成此操作,所以我现在有了这个

DECLARE 
    @tableName NVARCHAR(MAX),
    @sql NVARCHAR(MAX),
    @colName NVARCHAR(MAX);

DECLARE CUR_TABLE CURSOR FOR
    SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS

OPEN CUR_TABLE
FETCH NEXT FROM CUR_TABLE
INTO @tableName

WHILE @@FETCH_STATUS = 0
BEGIN
    
    SET @colName = '%employeeid%'
    SET @sql = 'SELECT COLUMN_NAME, TABLE_NAME, (SELECT COUNT(*) FROM ' + @tableName +') AS ROWS FROM INFORMATION_SCHEMA.COLUMNS where column_name like ' + ''' + @colName + ''';
    
    FETCH NEXT FROM CUR_TABLE
    INTO @tableName

END;

CLOSE CUR_TABLE
DEALLOCATE CUR_TABLE



EXEC sp_executesql @sql

但这并不不起作用,我想做的是使用我正在查找的列、表名称和表中的行数查询表。

我该如何解决这个问题?

Let’s say I’m looking for a specific column in my database so I have something like this

SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME like ‘%employeeid%’

But I also want to know how many rows each table has, I was told I can do this using Dynamic SQL so I have this now

DECLARE 
    @tableName NVARCHAR(MAX),
    @sql NVARCHAR(MAX),
    @colName NVARCHAR(MAX);

DECLARE CUR_TABLE CURSOR FOR
    SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS

OPEN CUR_TABLE
FETCH NEXT FROM CUR_TABLE
INTO @tableName

WHILE @@FETCH_STATUS = 0
BEGIN
    
    SET @colName = '%employeeid%'
    SET @sql = 'SELECT COLUMN_NAME, TABLE_NAME, (SELECT COUNT(*) FROM ' + @tableName +') AS ROWS FROM INFORMATION_SCHEMA.COLUMNS where column_name like ' + ''' + @colName + ''';
    
    FETCH NEXT FROM CUR_TABLE
    INTO @tableName

END;

CLOSE CUR_TABLE
DEALLOCATE CUR_TABLE



EXEC sp_executesql @sql

But this doesn't work, What I'm trying to do is query a table with the column I am looking for, with the table name, and number of rows in the table.

How can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

勿挽旧人 2025-01-19 16:12:10

您可以利用 SQL Server 的动态管理视图快速获取行数*。

查找具有名为“MyColumn”的列及其当前行的所有表:

select Schema_Name(t.schema_id) schemaName, t.name TableName, s.row_count
from sys.columns c
join sys.tables t on t.object_id = c.object_id
join sys.dm_db_partition_stats s on s.object_id = c.object_id and s.index_id <= 1
where c.name='MyColumn';

* 准确,但频繁更新的表可能会出现一些滞后

You can make use of SQL Server's dynamic management views to quickly obtain the row counts*.

Find all tables with a column named 'MyColumn' and their current rows:

select Schema_Name(t.schema_id) schemaName, t.name TableName, s.row_count
from sys.columns c
join sys.tables t on t.object_id = c.object_id
join sys.dm_db_partition_stats s on s.object_id = c.object_id and s.index_id <= 1
where c.name='MyColumn';

* Accurate except for frequently updated tables where there could be some lag

山人契 2025-01-19 16:12:10

以下使用 INFORMATION_SCHEMA、动态 SQL 和 STRING_AGG() 构建将返回单个结果集的查询。

DECLARE @ColumnName sysname = 'ProductID'

DECLARE @Newline VARCHAR(2) = CHAR(13) + CHAR(10)
DECLARE @SqlTemplate NVARCHAR(MAX) =
    + 'SELECT'
    + ' ColumnName = <ColumnNameString>,'
    + ' TableName = <TableSchemaAndNameString>,'
    + ' Rows = (SELECT COUNT(*) FROM <TableSchemaAndName>)'
    + @Newline
DECLARE @UnionSql NVARCHAR(100) = 'UNION ALL ' + @Newline

DECLARE @Sql NVARCHAR(MAX) = (
    SELECT STRING_AGG(
        REPLACE(REPLACE(REPLACE(
            @SqlTemplate
            , '<ColumnNameString>', QUOTENAME(C.COLUMN_NAME, ''''))
            , '<TableSchemaAndNameString>', QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, ''''))
            , '<TableSchemaAndName>', QUOTENAME(C.TABLE_SCHEMA) + '.' + QUOTENAME(C.TABLE_NAME))
        , @UnionSql)
        WITHIN GROUP(ORDER BY C.TABLE_SCHEMA, C.TABLE_NAME)
    FROM INFORMATION_SCHEMA.TABLES T
    JOIN INFORMATION_SCHEMA.COLUMNS C
        ON C.TABLE_SCHEMA = T.TABLE_SCHEMA
        AND C.TABLE_NAME = T.TABLE_NAME
    WHERE T.TABLE_TYPE = 'BASE TABLE' -- Omit views
    AND C.COLUMN_NAME = @ColumnName
)

SET @Sql = @Sql + 'ORDER BY Rows DESC, TableName' + @Newline

--PRINT @Sql
EXEC (@Sql)

我通过添加 TABLE_SCHEMA 对其进行了一些概括,以便它可以与 AdventureWorks 数据库一起使用。请参阅此 db<>fiddle 以获取工作演示。还包括对旧版 SQL Server 版本使用 FOR XML 而不是 STRING_AGG 的等效逻辑。

The following uses INFORMATION_SCHEMA, dynamic SQL, and STRING_AGG() to build a query that will return a single result set.

DECLARE @ColumnName sysname = 'ProductID'

DECLARE @Newline VARCHAR(2) = CHAR(13) + CHAR(10)
DECLARE @SqlTemplate NVARCHAR(MAX) =
    + 'SELECT'
    + ' ColumnName = <ColumnNameString>,'
    + ' TableName = <TableSchemaAndNameString>,'
    + ' Rows = (SELECT COUNT(*) FROM <TableSchemaAndName>)'
    + @Newline
DECLARE @UnionSql NVARCHAR(100) = 'UNION ALL ' + @Newline

DECLARE @Sql NVARCHAR(MAX) = (
    SELECT STRING_AGG(
        REPLACE(REPLACE(REPLACE(
            @SqlTemplate
            , '<ColumnNameString>', QUOTENAME(C.COLUMN_NAME, ''''))
            , '<TableSchemaAndNameString>', QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, ''''))
            , '<TableSchemaAndName>', QUOTENAME(C.TABLE_SCHEMA) + '.' + QUOTENAME(C.TABLE_NAME))
        , @UnionSql)
        WITHIN GROUP(ORDER BY C.TABLE_SCHEMA, C.TABLE_NAME)
    FROM INFORMATION_SCHEMA.TABLES T
    JOIN INFORMATION_SCHEMA.COLUMNS C
        ON C.TABLE_SCHEMA = T.TABLE_SCHEMA
        AND C.TABLE_NAME = T.TABLE_NAME
    WHERE T.TABLE_TYPE = 'BASE TABLE' -- Omit views
    AND C.COLUMN_NAME = @ColumnName
)

SET @Sql = @Sql + 'ORDER BY Rows DESC, TableName' + @Newline

--PRINT @Sql
EXEC (@Sql)

I generalized it a bit by adding TABLE_SCHEMA so that it could be used with the AdventureWorks database. See this db<>fiddle for a working demo. Also included is equivalent logic that uses FOR XML instead of STRING_AGG for older SQL Server versions.

挖鼻大婶 2025-01-19 16:12:10

假设您使用的是 SQL Server,这里有一个使用 sp_msforeachtable 的简写方法。

DECLARE @ColumnName NVARCHAR(200) = 'ContactID'

CREATE TABLE #T
(
    ColumnName NVARCHAR(200), 
    TableName NVARCHAR(200), 
    RecordCount INT
)

INSERT INTO #T (ColumnName, TableName)
SELECT 
    ColumnName = C.COLUMN_NAME, 
    TableName = '['+C.TABLE_SCHEMA+'].['+C.TABLE_NAME+']' 
FROM 
    INFORMATION_SCHEMA.COLUMNS C
WHERE 
    C.COLUMN_NAME LIKE '%' + @ColumnName + '%'

EXEC SP_MSFOREACHTABLE 'IF EXISTS(SELECT * FROM #T WHERE TableName = ''?'') UPDATE #T SET RecordCount = (SELECT COUNT(*) FROM ? ) WHERE TableName = ''?'''

SELECT 
    ColumnName,TableName,
    TableType = CASE 
                    WHEN RecordCount IS NULL 
                        THEN 'View' 
                        ELSE 'Table' 
                END,
    RecordCount
FROM 
    #T
ORDER BY
    CASE WHEN RecordCount IS NULL THEN 'View' ELSE 'Table' END

DROP TABLE #T

Assuming that you are using SQL Server, here is a shorthand way using sp_msforeachtable.

DECLARE @ColumnName NVARCHAR(200) = 'ContactID'

CREATE TABLE #T
(
    ColumnName NVARCHAR(200), 
    TableName NVARCHAR(200), 
    RecordCount INT
)

INSERT INTO #T (ColumnName, TableName)
SELECT 
    ColumnName = C.COLUMN_NAME, 
    TableName = '['+C.TABLE_SCHEMA+'].['+C.TABLE_NAME+']' 
FROM 
    INFORMATION_SCHEMA.COLUMNS C
WHERE 
    C.COLUMN_NAME LIKE '%' + @ColumnName + '%'

EXEC SP_MSFOREACHTABLE 'IF EXISTS(SELECT * FROM #T WHERE TableName = ''?'') UPDATE #T SET RecordCount = (SELECT COUNT(*) FROM ? ) WHERE TableName = ''?'''

SELECT 
    ColumnName,TableName,
    TableType = CASE 
                    WHEN RecordCount IS NULL 
                        THEN 'View' 
                        ELSE 'Table' 
                END,
    RecordCount
FROM 
    #T
ORDER BY
    CASE WHEN RecordCount IS NULL THEN 'View' ELSE 'Table' END

DROP TABLE #T
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文