用于检索 SQL 服务器中具有值的所有外键列的存储过程

Stored procedure to retrieve all foreign key columns with values in SQL server

我正在尝试创建一个存储过程,它将 return 外键列的列表 + 它们的值(一个 table 其中有两列),当提供 table 名称和其中的 ID table。保证 ID 是唯一的。结果应包含与外键列数相等的行数。如果未找到外键,则应生成 NULL 行,例如Key = NULL, Value = NULL.

考虑以下示例 tables 和数据:

员工 table:

 Id | Name       | AddressId | JobId 
----|------------|-----------|-------
 1  | John Smith | 2         | 3

Foreign keys:
- FK_Employee_Address
- FK_Employee_Job

地址 table:

 Id | Street    | Suite  | City     | Postal Code | CountryId 
----|-----------|--------|----------|-------------|-----------
 2  | 1 Main St | 101    | New York | 10001       | 4

Foreign keys:
- FK_Address_Country

国家/地区 table:

 Id | Name
----|------
 4  | USA

工作 table:

 Id  | Title
-----|-----------
 3   | Developer 

问题: 如何在生成的 SQL 查询中获取所有外键列及其值,每行一个?

测试用例1:

spGetForeignKeyColumns 'Employee', 1

Key       | Value
----------|------
AddressId | 2
JobId     | 3

测试用例2:

spGetForeignKeyColumns 'Address', 2

Key       | Value
----------|------
CountryId | 4

测试用例3:

spGetForeignKeyColumns 'Country', 4

Key       | Value
----------|------
NULL      | NULL

假设 Id 始终是 int 是安全的,因此不会有任何类型冲突。

尝试解决方案。我知道如何检索给定 table 没有值 的所有外键列SELECT 声明:

SELECT * FROM (    
    SELECT f.name AS ForeignKey, OBJECT_NAME(f.parent_object_id) AS TableName,
    COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
    OBJECT_NAME(f.referenced_object_id) AS ReferenceTableName,
    COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id) fk
WHERE TableName = @TableName

上面的 Employee table 会产生以下结果:

 ForeignKey          | TableName       | ColumnName | ReferenceTableName | ReferenceColumnName
---------------------|-----------------|------------|--------------------|---------------------
 FK_Employee_Address | Employee        | AddressId  | Address            | Id
 FK_Employee_Job     | Employee        | JobId      | Job                | Id

你们很亲近。我使用了您在问题中提供的查询,并添加了代码来检索相关 table 的主键。剩下的就是构建 SQL 来提取值并动态执行它。试试这个

DECLARE @TableName  VARCHAR(64) = 'Employee',
        @Id     INT = 1,
        @SQL    NVARCHAR(MAX) = '';

--Comment this out to debug
SELECT @SQL = @SQL + '
SELECT ''' + ColumnName + ''' as [Key], CONVERT(VARCHAR(255), ' + quotename(ColumnName) + ') as Value
FROM ' + quotename(TableName) + ' data
WHERE ' + quotename(primarykey) + ' = @Id
UNION
'
-- Uncomment this to debug...
--SELECT ColumnName, quotename(TableName), quotename(primarykey) 
--The column that returns null is the one with the problem
FROM (    
    SELECT f.name AS ForeignKey, 
        OBJECT_NAME(f.parent_object_id) AS TableName,
        COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
        OBJECT_NAME(f.referenced_object_id) AS ReferenceTableName,
        COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName,
        COL_NAME(ic.object_id, ic.column_id) as primarykey
    FROM sys.foreign_keys AS f
        INNER JOIN sys.foreign_key_columns fc ON f.OBJECT_ID = fc.constraint_object_id
        LEFT JOIN sys.index_columns ic ON ic.object_id = f.parent_object_id
        LEFT JOIN sys.indexes i ON i.object_id = ic.object_id and i.is_primary_key = 1 and i.index_id = ic.index_id) fk
WHERE TableName = @TableName

IF NULLIF(@SQL, '') IS NULL
BEGIN
    SELECT NULL AS [Key], NULL as Value
END
ELSE
BEGIN
    SET @SQL = LEFT(@SQL, LEN(@SQL) - 7)
    EXEC sp_executesql @SQL, N'@Id INT', @Id
END

我没有 运行 通过你所有的测试用例,但这应该让你非常接近。另外,我将该值转换为 VARCHAR,因为如果不是所有键都是整数,它会抛出错误。

希望对您有所帮助