获取sql server中包含完整详细信息(标识、空标签、主键)的所有列的列表,但不包含重复列
我需要自动化数据库升级过程。 因此,通过获取表的列结构,我需要创建update/insert/createsql语句的列结构 问题是我得到了重复的列名,因为约束也出现在我不需要的列表中。因此,有没有一种方法可以限制结果集中的约束 我正在使用下面的查询获取sql server中包含完整详细信息(标识、空标签、主键)的所有列的列表,但不包含重复列,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我需要自动化数据库升级过程。 因此,通过获取表的列结构,我需要创建update/insert/createsql语句的列结构 问题是我得到了重复的列名,因为约束也出现在我不需要的列表中。因此,有没有一种方法可以限制结果集中的约束 我正在使用下面的查询 SELECT c.NAME 'Column Name' ,t.NAME 'Data type' ,c.max_length 'Max Length' ,c.precision ,c.scale ,c.is_nullable AS 'Is Nulla
SELECT c.NAME 'Column Name'
,t.NAME 'Data type'
,c.max_length 'Max Length'
,c.precision
,c.scale
,c.is_nullable AS 'Is Nullable'
,c.is_identity AS 'Is Identity'
,ISNULL(i.is_primary_key, 0) 'Primary Key'
,i.type_desc
FROM fblfeb12.sys.columns c
INNER JOIN fblfeb12.sys.types t ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN fblfeb12.sys.index_columns ic ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN fblfeb12.sys.indexes i ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
WHERE c.object_id = OBJECT_ID('table name')
结果集:
Pms_ID uniqueidentifier 16 0 0 0 0 CLUSTERED
Pms_PRODMODELID uniqueidentifie 16 0 0 1 0NONCLUSTERED
Pms_PRODMODELID uniqueidentifier 16 0 0 10NONCLUSTERED
Pms_PRODMODELID uniqueidentifier 16 0 0 10NONCLUSTERED
Pms_ATTRIBUTEID uniqueidentifier 16 0 0 10NONCLUSTERED
Pms_ATTRIBUTEID uniqueidentifier 16 0 0 0NONCLUSTERED
Pms_ATTRIBUTEID uniqueidentifier 16 0 0 1NONCLUSTERED
其中PRODMODELID
,ATTRIBUTEID
出现3次
我只需要外键列,但这里我得到了索引,我不需要约束
我需要列名、数据类型、标识、主键、可空、外键
如果我做错了什么,你能给我提供更好的解决方案吗?如果你使用“与众不同”会发生什么?所以
“我只需要外键列,但这里我得到的是索引,我不需要约束。”
如果需要获取外键列,则不能使用此选项。并删除到sys.index_列和sys.index的联接?问题是您在列中包含了所有索引。考虑一下这个简单的表格:
CREATE TABLE #T (ID INT NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY);
CREATE INDEX IX_T_ID ON #T (ID);
运行查询的自适应时:
SELECT c.name, i.name, i.is_primary_key
FROM tempdb.sys.columns c
LEFT OUTER JOIN tempdb.sys.index_columns ic
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN tempdb.sys.indexes i
ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
WHERE c.object_id = OBJECT_ID('tempdb..#T');
对于包含该列(键或非键)的每个索引,列名都将重复,因此结果将是:
name name is_primary_key
ID PK_T_ID 1
ID IX_T_ID 0
由于您只关心主键,因此可以在连接到sys.indexes
中应用a筛选器,以仅返回主键,尽管您需要将index_列
和索引
之间的连接设置为内部连接,但是要保持从列
到索引列
的外部连接,这需要稍微重新排列连接,因此上述内容将变为:
SELECT c.name, i.name, i.is_primary_key
FROM tempdb.sys.columns c
LEFT OUTER JOIN (tempdb.sys.index_columns ic
INNER JOIN tempdb.sys.indexes i
ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
AND i.is_primary_key = 1) -- ONLY PRIMARY KEYS
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
WHERE c.object_id = OBJECT_ID('tempdb..#T');
这将删除重复的结果。最后,您可以查询sys.foreign\u key\u columns
,以确定该列是否引用了另一个表,该表给出了以下最终查询:
SELECT c.NAME AS [Column Name]
,t.NAME AS [Data type]
,c.max_length AS [Max Length]
,c.precision
,c.scale
,c.is_nullable AS [Is Nullable]
,c.is_identity AS [Is Identity]
,ISNULL(i.is_primary_key, 0) [Primary Key]
,i.type_desc
,OBJECT_SCHEMA_NAME(fk.object_id) + '.' + OBJECT_NAME(fk.object_id) + ' (' + fk.Name + ')' AS [Foreign Key]
FROM sys.columns c
INNER JOIN sys.types t
ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN (sys.index_columns ic
INNER JOIN sys.indexes i
ON ic.object_id = i.object_id
AND i.is_primary_key = 1
AND ic.index_id = i.index_id)
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT JOIN sys.foreign_key_columns fkc
ON fkc.parent_object_id = c.object_id
AND fkc.parent_column_id = c.column_id
LEFT JOIN sys.columns fk
ON fk.object_id = fkc.referenced_object_id
AND fk.column_id = fkc.referenced_column_id
WHERE c.object_id = OBJECT_ID('table')
ORDER BY c.Column_ID;
注意:我已经将您的列别名从单引号改为方括号,因为不推荐使用单引号(更不用说)如果您取消对sys.index\u columns
表的连接,则每个索引只能获得一行。发生这种乘法是因为索引包含N列,因此在结果集中重复N次。最好修复根本原因,而不是在错误上贴绷带。是的,我也在查看问题所在,但我还没有找到它。看起来,如果他删除了与index_列的左连接,那么就可以了,但他不知道它是否是主键。我想这必须是其他的方法,但我对这些表不是很熟悉。输入时,我需要一个表的所有列,不仅仅是主键,我不需要重复项。有什么方法可以得到这个结果吗。这会提供所有列,并删除重复项。你真的试过运行我发布的查询吗?这个请求太棒了!但是,当我们的列参与多个外键约束时,有一个小问题。假设我们有表prob
,有列建筑id
,楼层id
和房间id
。假设一栋建筑(在同名表中)仅由建筑id
标识,而一层楼(在同名表中)由建筑id
+楼层id
标识,一个房间(在同名表中)由建筑id
+楼层id
+房间id
标识。然后,prob.building\u id
列将在上述请求中显示3次,而floor\u id
列将显示两次。这可以解决吗?
SELECT c.NAME AS [Column Name]
,t.NAME AS [Data type]
,c.max_length AS [Max Length]
,c.precision
,c.scale
,c.is_nullable AS [Is Nullable]
,c.is_identity AS [Is Identity]
,ISNULL(i.is_primary_key, 0) [Primary Key]
,i.type_desc
,OBJECT_SCHEMA_NAME(fk.object_id) + '.' + OBJECT_NAME(fk.object_id) + ' (' + fk.Name + ')' AS [Foreign Key]
FROM sys.columns c
INNER JOIN sys.types t
ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN (sys.index_columns ic
INNER JOIN sys.indexes i
ON ic.object_id = i.object_id
AND i.is_primary_key = 1
AND ic.index_id = i.index_id)
ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT JOIN sys.foreign_key_columns fkc
ON fkc.parent_object_id = c.object_id
AND fkc.parent_column_id = c.column_id
LEFT JOIN sys.columns fk
ON fk.object_id = fkc.referenced_object_id
AND fk.column_id = fkc.referenced_column_id
WHERE c.object_id = OBJECT_ID('table')
ORDER BY c.Column_ID;