用于检索 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,因为如果不是所有键都是整数,它会抛出错误。
希望对您有所帮助
我正在尝试创建一个存储过程,它将 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,因为如果不是所有键都是整数,它会抛出错误。
希望对您有所帮助