T-SQL:如何查找列表中是否存在列

时间:2016-11-11 17:44:36

标签: sql sql-server tsql ssms

我的目标是从存储过程中获取一个表列表,然后返回这些表的名称及其行数,以及每个表中是否存在ModifiedDate列。

到目前为止,它几乎可以工作,但是这个当前的代码给了我一些表,其中ModifiedDate表示存在且不存在。我猜这个问题出在最后一个选择语句中。

-- Create temporary table
CREATE TABLE #TempTable
(
  [object_name] NVARCHAR(255) ,
  [object_id] NVARCHAR(255),
  [row_count] INT
)

-- Insert table names, object id and row count into temp table
INSERT  INTO #TempTable
    SELECT DISTINCT
            [object_name] = SCHEMA_NAME(o.[schema_id]) + '.' + o.name ,
            o.object_id,
            ddps.row_count
    FROM    sys.dm_sql_referenced_entities('dbo.spMyStoredProcedure',
                                           'OBJECT') d
            JOIN sys.objects o ON d.referenced_id = o.[object_id]
            INNER JOIN sys.indexes AS i ON i.object_id = o.object_id
            INNER JOIN sys.dm_db_partition_stats AS ddps ON i.object_id = ddps.object_id
                                                          AND i.index_id = ddps.index_id
    WHERE   o.[type] IN ( 'U', 'V' )
            AND i.index_id < 2
            AND o.is_ms_shipped = 0;

-- Join temp table to query that searches for a ModifiedDate column
SELECT  DISTINCT t2.[object_name] AS 'TableName' ,
    t2.[row_count] AS 'RowCount' ,
    CASE
        WHEN t1.name ='modifiedDate' THEN 'Yes'
        WHEN t1.name <> 'modifiedDate' THEN 'No'
    END AS 'ModifiedDateExists'
FROM    sys.columns AS t1
    RIGHT JOIN #TempTable AS t2 ON t1.object_id = t2.object_id;

-- Delete temp table
IF ( OBJECT_ID('mydbhere..#TempTable') IS NOT NULL )
BEGIN
    DROP TABLE #TempTable
END;

1 个答案:

答案 0 :(得分:1)

问题是sys.columns将包含1个对象(表)的多个记录(每列一个)。你需要1-1的关系。你使用的独特之处在于隐藏了你有更多行(每个字段为1)的事实。所以你需要确保从sys.columns和#TempTable之间的连接只返回1条记录。这可以通过仅搜索modifiedDate并允许右连接中存在NULL来表示它不会退出。

SELECT  t2.[object_name] AS 'TableName' 
     ,  t2.[row_count] AS 'RowCount' 
     , case when t1.name is not null then 'YES' else 'No' as 'ModifiedDateExists'
FROM sys.columns AS t1
RIGHT JOIN #TempTable AS t2 
  ON t1.object_id = t2.object_id
 and t1.name ='modifiedDate'

由于SQL Server会阻止相同的命名对象(列/字段)出现在表中,因此只需限制该列;所有其他记录都会导致Null,然后在我们的case语句中我们可以说是或否。

#tempTable中的所有表都将被返回但只有1列。

一般的经验法则是避免区别,除非你真正意味着它,因为它通常只是在连接,限制或其他东西上隐藏问题。