列出一个table的所有外键,多个外键指向同一个table
List all foreign keys of a table, multiple foreign keys to same table
我使用以下 SQL 来查询给定的 table 的键(主键和外键)及其描述。我正在使用 SQL Server 2005。
SELECT c.name 'Column Name' ,
t.name 'Data type' ,
c.max_length 'Max Length' ,
c.precision ,
c.scale ,
c.is_nullable ,
ISNULL(i.is_primary_key, 0) 'Primary Key' ,
CAST (( SELECT COUNT(*)
FROM ( SELECT cx.object_id
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cx ON fkc.parent_column_id = cx.column_id
AND fkc.parent_object_id = cx.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cx.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) xxx
) AS BIT) AS 'Foreign Key' ,
( SELECT OBJECT_SCHEMA_NAME(fkc.referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Schema Name' ,
( SELECT OBJECT_NAME(referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced table' ,
( SELECT cref.name
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced column name' ,
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('[dbo].Cards') = sep.major_id
AND c.column_id = sep.minor_id
) Description FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id
AND ic.index_id = i.index_id WHERE c.object_id = OBJECT_ID('[dbo].Cards');
该查询对所有 table 都有效,除非 table 有两个外键指向同一个 table。
我得到的错误是,
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
我做错了什么?
我已经解决了我自己的问题。
张贴在这里以防有人偶然发现这个问题。
SELECT c.name 'Column Name' ,
t.name 'Data type' ,
c.max_length 'Max Length' ,
c.precision ,
c.scale ,
c.is_nullable ,
ISNULL(i.is_primary_key, 0) 'Primary Key' ,
CAST (( SELECT COUNT(*)
FROM ( SELECT cx.object_id
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cx ON fkc.parent_column_id = cx.column_id
AND fkc.parent_object_id = cx.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cx.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) xxx
) AS BIT) AS 'Foreign Key' ,
( SELECT TOP 1 OBJECT_SCHEMA_NAME(fkc.referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Schema Name' ,
( SELECT TOP 1 OBJECT_NAME(referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced table' ,
( SELECT TOP 1 cref.name
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced column name' ,
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('[dbo].Cards') = sep.major_id
AND c.column_id = sep.minor_id
) Description FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id
AND ic.index_id = i.index_id WHERE c.object_id = OBJECT_ID('[dbo].Cards');
我没有检查你的第二个查询,但问题仍然存在:
返回超过1个值的子查询是这个
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('person.stateProvince') = sep.major_id
AND c.column_id = sep.minor_id
) Description
您应该在 where 子句中添加附加条件:
and class = 1 -- OBJECT_OR_COLUMN
您的查询不考虑 table 的 1 个以上索引,加入 c.column_id = sep.minor_id 您会得到更多行,因为当 class 为 7 ( index) minor_id 是索引id,不是列id
我使用以下 SQL 来查询给定的 table 的键(主键和外键)及其描述。我正在使用 SQL Server 2005。
SELECT c.name 'Column Name' ,
t.name 'Data type' ,
c.max_length 'Max Length' ,
c.precision ,
c.scale ,
c.is_nullable ,
ISNULL(i.is_primary_key, 0) 'Primary Key' ,
CAST (( SELECT COUNT(*)
FROM ( SELECT cx.object_id
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cx ON fkc.parent_column_id = cx.column_id
AND fkc.parent_object_id = cx.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cx.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) xxx
) AS BIT) AS 'Foreign Key' ,
( SELECT OBJECT_SCHEMA_NAME(fkc.referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Schema Name' ,
( SELECT OBJECT_NAME(referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced table' ,
( SELECT cref.name
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced column name' ,
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('[dbo].Cards') = sep.major_id
AND c.column_id = sep.minor_id
) Description FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id
AND ic.index_id = i.index_id WHERE c.object_id = OBJECT_ID('[dbo].Cards');
该查询对所有 table 都有效,除非 table 有两个外键指向同一个 table。
我得到的错误是,
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
我做错了什么?
我已经解决了我自己的问题。
张贴在这里以防有人偶然发现这个问题。
SELECT c.name 'Column Name' ,
t.name 'Data type' ,
c.max_length 'Max Length' ,
c.precision ,
c.scale ,
c.is_nullable ,
ISNULL(i.is_primary_key, 0) 'Primary Key' ,
CAST (( SELECT COUNT(*)
FROM ( SELECT cx.object_id
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cx ON fkc.parent_column_id = cx.column_id
AND fkc.parent_object_id = cx.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cx.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) xxx
) AS BIT) AS 'Foreign Key' ,
( SELECT TOP 1 OBJECT_SCHEMA_NAME(fkc.referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Schema Name' ,
( SELECT TOP 1 OBJECT_NAME(referenced_object_id)
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced table' ,
( SELECT TOP 1 cref.name
FROM sys.foreign_key_columns fkc
INNER JOIN sys.columns cy ON fkc.parent_column_id = cy.column_id
AND fkc.parent_object_id = cy.object_id
INNER JOIN sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
WHERE cy.column_id = c.column_id
AND fkc.parent_object_id = OBJECT_ID('[dbo].Cards')
) 'Referenced column name' ,
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('[dbo].Cards') = sep.major_id
AND c.column_id = sep.minor_id
) Description FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id
AND ic.index_id = i.index_id WHERE c.object_id = OBJECT_ID('[dbo].Cards');
我没有检查你的第二个查询,但问题仍然存在: 返回超过1个值的子查询是这个
( SELECT sep.value [Description]
FROM sys.extended_properties sep
WHERE OBJECT_ID('person.stateProvince') = sep.major_id
AND c.column_id = sep.minor_id
) Description
您应该在 where 子句中添加附加条件:
and class = 1 -- OBJECT_OR_COLUMN
您的查询不考虑 table 的 1 个以上索引,加入 c.column_id = sep.minor_id 您会得到更多行,因为当 class 为 7 ( index) minor_id 是索引id,不是列id