我编写了一个外键脚本,并使用sys 表来获取重建脚本所需的所有详细信息:
SELECT FK.[name]
--
,FK.[delete_referential_action_desc]
,FK.[update_referential_action_desc]
--
,KC.[constraint_column_id]
,PS.[name]
,P.[name]
,PTC.[name]
--
,RTS.[name]
,RT.[name]
,RTC.[name]
FROM [sys].[foreign_keys] FK
INNER JOIN [sys].[objects] P
ON FK.[parent_object_id] = P.[object_id]
INNER JOIN [sys].[schemas] PS
ON P.[schema_id] = PS.[schema_id]
INNER JOIN [sys].[foreign_key_columns] KC
ON FK.[object_id] = KC.[constraint_object_id]
-- parent columns
INNER JOIN [sys].[columns] PTC
ON P.[object_id] = PTC.[object_id]
AND KC.[parent_column_id] = PTC.[column_id]
-- referenced table schema, name and columns
INNER JOIN [sys].[objects] RT
ON KC.[referenced_object_id] = RT.[object_id]
INNER JOIN [sys].[schemas] RTS
ON RT.[schema_id] = RTS.[schema_id]
INNER JOIN [sys].[columns] RTC
ON RT.[object_id] = RTC.[object_id]
AND KC.[referenced_column_id] = RTC.[column_id];
这甚至会给我每个表的架构细节。现在,您可以使用这条 T-SQL 语句来做您想做的事。请注意,我将其包装在 CTE 中只是为了使内容更具可读性。此外,我们还有第二个CTE 来处理外键由多列组成的情况。
WITH DataSource AS
(
SELECT FK.[name] AS [FK_Name]
--
,FK.[delete_referential_action_desc]
,FK.[update_referential_action_desc]
--
,KC.[constraint_column_id] AS [FK_ColumnPos]
,PS.[name] AS [PT_SCHEMA_NAME]
,P.[name] AS [PT_NAME]
,PTC.[name] AS [PT_COLUMN_NAME]
--
,RTS.[name] AS [RF_SCHEMA_NAME]
,RT.[name] AS [RF_NAME]
,RTC.[name] AS [RF_COLUMN_NAME]
FROM [sys].[foreign_keys] FK
INNER JOIN [sys].[objects] P
ON FK.[parent_object_id] = P.[object_id]
INNER JOIN [sys].[schemas] PS
ON P.[schema_id] = PS.[schema_id]
INNER JOIN [sys].[foreign_key_columns] KC
ON FK.[object_id] = KC.[constraint_object_id]
-- parent columns
INNER JOIN [sys].[columns] PTC
ON P.[object_id] = PTC.[object_id]
AND KC.[parent_column_id] = PTC.[column_id]
-- referenced table schema, name and columns
INNER JOIN [sys].[objects] RT
ON KC.[referenced_object_id] = RT.[object_id]
INNER JOIN [sys].[schemas] RTS
ON RT.[schema_id] = RTS.[schema_id]
INNER JOIN [sys].[columns] RTC
ON RT.[object_id] = RTC.[object_id]
AND KC.[referenced_column_id] = RTC.[column_id]
), DataSourcePrecalc AS
(
SELECT DISTINCT
[FK_Name]
,[delete_referential_action_desc]
,[update_referential_action_desc]
,[PT_SCHEMA_NAME]
,[PT_NAME]
,STUFF
(
(
SELECT ', [' + DS1.[PT_COLUMN_NAME] + ']'
FROM DataSource DS1
WHERE DS1.[FK_Name] = DS.[FK_Name]
AND DS1.[PT_NAME] = DS.[PT_NAME]
ORDER BY DS1.[FK_ColumnPos]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,2
,''
) AS [PT_COLUMNS]
,[RF_SCHEMA_NAME]
,[RF_NAME]
,STUFF
(
(
SELECT ', [' + DS2.[RF_COLUMN_NAME] + ']'
FROM DataSource DS2
WHERE DS2.[FK_Name] = DS.[FK_Name]
AND DS2.[RF_NAME] = DS.[RF_NAME]
ORDER BY DS2.[FK_ColumnPos]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,2
,''
) AS [RT_COLUMNS]
FROM DataSource DS
)
SELECT
'
ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] DROP CONSTRAINT [' + [FK_Name] + '];
ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] WITH CHECK ADD CONSTRAINT [' + [FK_Name] + '] FOREIGN KEY(' + [PT_COLUMNS] + ')
REFERENCES [' + [RF_SCHEMA_NAME] + '].[' + [RF_NAME] + '] (' + [RT_COLUMNS] + ')
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [' + [PT_SCHEMA_NAME] + '].[' + [PT_NAME] + '] CHECK CONSTRAINT [' + [FK_Name] + '];
'
FROM DataSourcePrecalc;
注意,这里的 CASCADE 值是硬编码的。如果需要,您可以添加一些其他逻辑,使用原始逻辑。这里更重要的是为我们带来所有需要的详细信息的初始查询。有了它,你就可以为所欲为。