【问题标题】:How to find List Tables using columns value如何使用列值查找列表表
【发布时间】:2023-04-01 22:00:01
【问题描述】:

我在数据库中有 500 多个表。所有表都有几列。其中有些表有'CMDFLAG'列,列的值可能有'C'或'D'或'M'。

我的要求是找到 CMDFLAG 为 'C'or'D' 或 'M' 的表的列表。

Table Name    Column Name   Value
----------     -----------   -----
Table_A         CMDFLAG      C
Table_A         CMDFLAG      D
Table_A         CMDFLAG      M
Table_B         CMDFLAG      C
Table_B         CMDFLAG      D
Table_C         CMDFLAG      M

等等……

我可以使用 INFORMATION_SCHEMA.COLUMNS 找到这些具有 CMDFLAG 列的表的列表。但我想查找 CMDFLAG 列具有值“C”或“D”或“M”的表列表。

我已经回答了几个问题,但无法满足我的要求。此外,我想使用简单查询而不是过程。

【问题讨论】:

  • 不是一个简单的查询。
  • 我知道如何做到这一点的唯一方法是使用动态 sql。

标签: sql sql-server sql-server-2012 database-schema


【解决方案1】:

试试这个。我必须使用动态查询和临时表,因为EXEC 不适用于公用表表达式。

CREATE TABLE #t1
(
    tableName varchar(30),
    RN INT
)

CREATE TABLE #t2
(
    tableName varchar(30),
    columnName varchar(30),
    value char(1)
)

INSERT INTO #t1
SELECT C.TABLE_NAME, ROW_NUMBER() OVER(ORDER BY TABLE_NAME) AS RN
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'CMDFLAG'

DECLARE @COUNT AS INT = (SELECT COUNT(1) FROM #t1)
DECLARE @Iterator AS INT = 1
DECLARE @tableName AS VARCHAR(30)
DECLARE @script AS  VARCHAR(200)

WHILE @Iterator <= @COUNT
BEGIN
    SELECT @tableName = (SELECT tableName FROM #t1 WHERE RN = @Iterator)
    SELECT @script = 'SELECT '''+@tableName+''', ''CMDFLAG'', CMDFLAG FROM '+@tableName+' GROUP BY CMDFLAG'

    INSERT INTO #t2
    EXEC(@script)

    SELECT @Iterator = @Iterator + 1

END

SELECT * FROM #t2

DROP TABLE #t1
DROP TABLE #t2

【讨论】:

    【解决方案2】:

    你可以这样做。

    SET NOCOUNT ON;
    
    DECLARE @colname SYSNAME='CMDFLAG';
    
    CREATE TABLE #tablenames(tablename SYSNAME,colname SYSNAME,colval NVARCHAR(128));
    DECLARE @dsql NVARCHAR(MAX)= (
        SELECT 
            N'INSERT INTO #tablenames(tablename,colname,colval)'+
            N'SELECT DISTINCT ' +
                'tablename='''+REPLACE(t.TABLE_NAME,N'''',N'''''')+N''','+
                'colname='''+REPLACE(@colname,N'''',N'''''')+N''','+
                'colval='+QUOTENAME(@colname)+N' '+
            N'FROM '+QUOTENAME(t.TABLE_SCHEMA)+N'.'+QUOTENAME(t.TABLE_NAME)+N' '+
            N'WHERE '+QUOTENAME(@colname)+N' IN (''C'',''D'',''M'');'
        FROM 
            INFORMATION_SCHEMA.TABLES AS t
            INNER JOIN INFORMATION_SCHEMA.COLUMNS AS c ON
                c.TABLE_SCHEMA=t.TABLE_SCHEMA AND
                c.TABLE_NAME=t.TABLE_NAME
        WHERE
            t.TABLE_TYPE='BASE TABLE' AND
            c.COLUMN_NAME=@colname
        FOR 
            XML PATH('')
    );
    
    EXECUTE sp_executesql @dsql;
    
    SELECT * FROM #tablenames ORDER BY tablename;
    DROP TABLE #tablenames;
    

    【讨论】:

    • 感谢您的精彩尝试。但它只返回表列表。但是如前所述,我需要 TableName 、 ColumnName 、 Value 。
    • @AbdurRahman 那么这些表中的每一列将只包含一个不同的 CMDFLAG 值?或者您是否想要为该列中 CMDFLAG 的每个不同值添加一个条目?
    • ,,该列中 CMDFLAG 的每个不同值的条目
    【解决方案3】:

    这样的事情怎么样:

    DECLARE @ColumnName sysname = 'CMDFLAG', @Sql NVARCHAR(MAX)
    
    IF OBJECT_ID(N'TempDB.dbo.#Results', N'U') IS NULL
        CREATE TABLE #Results(TableName SYSNAME, RowCounts INT)
    ELSE
        TRUNCATE TABLE #Results
    
    SELECT
        @Sql = 'INSERT INTO #Results '
                + STUFF((
                            SELECT
                                'UNION ALL SELECT Table_Name = ' 
                                    + QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, '''') 
                                    + ', NumRows = COUNT(*)'
                                    + ' FROM ' 
                                    + QUOTENAME(C.TABLE_SCHEMA) + '.' 
                                    + QUOTENAME(C.TABLE_NAME )
                                    + ' WHERE ' + QUOTENAME(C.COLUMN_NAME) + ' IN(''C'', ''D'', ''M'') '
                                    + ' GROUP BY ' + QUOTENAME(C.COLUMN_NAME)
                                    + ' HAVING COUNT(*) > 0 '
                            FROM
                                INFORMATION_SCHEMA.COLUMNS C
                                CROSS APPLY
                                (
                                    SELECT
                                        T.TABLE_SCHEMA, T.TABLE_NAME
                                    FROM
                                        INFORMATION_SCHEMA.TABLES T
                                    WHERE
                                        T.TABLE_TYPE = 'BASE TABLE'
                                        AND T.TABLE_SCHEMA = C.TABLE_SCHEMA
                                        AND T.TABLE_NAME = C.TABLE_NAME
                                ) T
                            WHERE
                                C.COLUMN_NAME = @ColumnName
                FOR XML PATH(''), type).value('.', 'nvarchar(max)'), 1, 10, '')
    
    EXEC(@Sql)
    SELECT * FROM #Results
    

    更新

    好的,这应该可以满足您的要求:

    DECLARE @ColumnName sysname = 'CMDFLAG', @Sql NVARCHAR(MAX)
    
    IF OBJECT_ID(N'TempDB.dbo.#Results', N'U') IS NULL
        CREATE TABLE #Results(TableName SYSNAME, ColumnName sysname, Value NVARCHAR(25))
    ELSE
        TRUNCATE TABLE #Results
    
    SELECT
        @Sql = 'INSERT INTO #Results '
                + STUFF((
                            SELECT
                                'UNION ALL SELECT DISTINCT Table_Name = ' 
                                    + QUOTENAME(C.TABLE_SCHEMA + '.' + C.TABLE_NAME, '''') 
                                    + ', '  + QUOTENAME(C.COLUMN_NAME, '''')
                                    + ', '  + QUOTENAME(C.COLUMN_NAME)
                                    + ' FROM ' 
                                    + C.TABLE_SCHEMA + '.' 
                                    + C.TABLE_NAME 
                                    + ' WHERE ' + QUOTENAME(C.COLUMN_NAME) + ' IN(''C'', ''D'', ''M'') '
                            FROM
                                INFORMATION_SCHEMA.COLUMNS C
                                CROSS APPLY
                                (
                                    SELECT
                                        T.TABLE_SCHEMA, T.TABLE_NAME
                                    FROM
                                        INFORMATION_SCHEMA.TABLES T
                                    WHERE
                                        T.TABLE_TYPE = 'BASE TABLE'
                                        AND T.TABLE_SCHEMA = C.TABLE_SCHEMA
                                        AND T.TABLE_NAME = C.TABLE_NAME
                                ) T
                            WHERE
                                C.COLUMN_NAME = @ColumnName
                FOR XML PATH(''), type).value('.', 'nvarchar(max)'), 1, 10, '')
    EXEC(@Sql)
    SELECT * FROM #Results
    

    【讨论】:

    • 感谢您的精彩尝试。但它只返回表列表。但是如前所述,我需要 TableName 、 ColumnName 、 Value 。
    • 更新回答我的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多