T-SQL:如何查找表列表中是否存在列
T-SQL: How to find if a column exists in a list of tables
我的目标是从存储过程中获取 table 的列表,然后 return 这些 table 的名称及其行数,如果 [=每个 table.
中存在 12=] 列
到目前为止,它几乎可以正常工作,但是当前的代码让我返回了一些 tables,它说 ModifiedDate
既存在又不存在。我猜问题在于最后的 select 语句。
-- 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;
问题是 sys.columns
将包含 1 个对象 (table) 的多条记录(每列一个)。你需要一对一的关系。您使用的独特之处在于隐藏了这样一个事实,即您会有 很多 行(实际上每个字段 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 服务器将阻止相同命名的对象 (column/field) 在 table 中,只需限制在该列即可;所有其他记录将导致 Null,然后在我们的 case 语句中我们可以说是或否。
将返回 #tempTable
中的所有 table,但仅返回 1 列。
一般的经验法则是避免 Distinct,除非你真的是认真的,因为它通常只是隐藏连接、限制或其他问题。
我的目标是从存储过程中获取 table 的列表,然后 return 这些 table 的名称及其行数,如果 [=每个 table.
中存在 12=] 列到目前为止,它几乎可以正常工作,但是当前的代码让我返回了一些 tables,它说 ModifiedDate
既存在又不存在。我猜问题在于最后的 select 语句。
-- 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;
问题是 sys.columns
将包含 1 个对象 (table) 的多条记录(每列一个)。你需要一对一的关系。您使用的独特之处在于隐藏了这样一个事实,即您会有 很多 行(实际上每个字段 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 服务器将阻止相同命名的对象 (column/field) 在 table 中,只需限制在该列即可;所有其他记录将导致 Null,然后在我们的 case 语句中我们可以说是或否。
将返回 #tempTable
中的所有 table,但仅返回 1 列。
一般的经验法则是避免 Distinct,除非你真的是认真的,因为它通常只是隐藏连接、限制或其他问题。