从 sys 表编写外键脚本——与具有多列的键作斗争
Scripting foreign keys from sys tables -- struggling with keys that have multiple columns
大家好,提前致谢。
我一直在尝试编写现有数据库中的外键脚本,但在引用多列的键时遇到问题。
我使用的脚本如下:
SELECT
'FOREIGN_KEY' as KeyType,'ALTER TABLE ' + OBJECT_NAME(f.parent_object_id) +
' WITH CHECK ADD CONSTRAINT ' + '[' + OBJECT_NAME(f.object_id) +
']' + ' FOREIGN KEY ([' + col_name(fc.parent_object_id,fc.parent_column_id) +
']) REFERENCES ' + OBJECT_NAME(f.referenced_object_id) +
' ([' + COL_NAME(fc.referenced_object_id,fc.referenced_column_id) + ']) ALTER TABLE ' +
OBJECT_NAME(f.parent_object_id) + ' CHECK CONSTRAINT [' +
OBJECT_NAME(f.object_id) + ']' as result
FROM
sys.foreign_keys AS f
INNER JOIN
sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN
sys.tables t
ON t.OBJECT_ID = fc.referenced_object_id
WHERE
OBJECT_NAME (f.referenced_object_id) = @TableName
这将 return 所需的外键,但如上所述,我遇到以下结果的问题:
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([PatientCode]) REFERENCES [dbo].[TreatmentPlans] ([PatientCode]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([TPNumber]) REFERENCES [dbo].[TreatmentPlans] ([TPNumber]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
我需要的输出应该是这样的:
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([Patientcode],[TPNumber]) REFERENCES [dbo].[TreatmentPlans] ([Patientcode],[TPNumber]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
如有任何帮助,我们将不胜感激。
谢谢
下面是代码示例,希望您能根据自己的需要采纳:
declare @tName sysname;
set @tName = 'dbo.TableName';
with vPKColumns as (
select c.object_id, c.column_id, c.name, ixc.key_ordinal
from sys.key_constraints pk
join sys.index_columns ixc on ixc.object_id = pk.parent_object_id and ixc.index_id = pk.unique_index_id
join sys.columns c on c.object_id = pk.parent_object_id and c.column_id = ixc.column_id
where pk.parent_object_id = object_id(@tName) and pk.type = 'PK'
),
vFKs as (
select
quotename(fk.name) as name,
fk.parent_object_id,
fk.object_id,
case
when fk.delete_referential_action_desc collate database_default = 'NO_ACTION' then NULL
else ' on delete ' + replace(lower(FK.delete_referential_action_desc) collate database_default, '_', ' ')
end as onDelete,
case
when fk.update_referential_action_desc collate database_default = 'NO_ACTION' then NULL
else ' on update ' + replace(lower(FK.update_referential_action_desc) collate database_default, '_', ' ')
end as onUpdate
from sys.foreign_keys fk
where exists (
select 1
from sys.foreign_key_columns fkc
join vPKColumns pkc on pkc.object_id = fkc.referenced_object_id and pkc.column_id = fkc.referenced_column_id
where fkc.referenced_object_id = fk.referenced_object_id
)
)
select
'alter table ' + quotename(s.name) + '.' + quotename(t.name) + '
with nocheck add constraint ' + fk.name + ' foreign key (' + stuff(
(select ', ' + quotename(c.name)
from sys.foreign_key_columns fkc
join sys.columns c on c.object_id = fkc.parent_object_id and c.object_id = fkc.parent_object_id and c.column_id = fkc.parent_column_id
where fkc.constraint_object_id = fk.object_id
order by fkc.constraint_column_id
for xml path(''), type).value('text()[1]','nvarchar(max)'),1,2,'') + ') references ' + @tName + ' (' +
stuff(
(select ', ' + quotename(pkc.name)
from vPKColumns pkc
order by pkc.key_ordinal
for xml path(''), type).value('text()[1]','nvarchar(max)'),1,2,'') + ')' +
isnull('
' + onDelete, '') +
isnull('
' + onUpdate, '') + ';
GO
alter table ' + quotename(s.name) + '.' + quotename(t.name) + '
check constraint ' + fk.name + ';
GO'
from vFKs fk
join sys.tables t on t.object_id = fk.parent_object_id
join sys.schemas s on s.schema_id = t.schema_id
order by s.name, t.name, fk.name;
大家好,提前致谢。
我一直在尝试编写现有数据库中的外键脚本,但在引用多列的键时遇到问题。
我使用的脚本如下:
SELECT
'FOREIGN_KEY' as KeyType,'ALTER TABLE ' + OBJECT_NAME(f.parent_object_id) +
' WITH CHECK ADD CONSTRAINT ' + '[' + OBJECT_NAME(f.object_id) +
']' + ' FOREIGN KEY ([' + col_name(fc.parent_object_id,fc.parent_column_id) +
']) REFERENCES ' + OBJECT_NAME(f.referenced_object_id) +
' ([' + COL_NAME(fc.referenced_object_id,fc.referenced_column_id) + ']) ALTER TABLE ' +
OBJECT_NAME(f.parent_object_id) + ' CHECK CONSTRAINT [' +
OBJECT_NAME(f.object_id) + ']' as result
FROM
sys.foreign_keys AS f
INNER JOIN
sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN
sys.tables t
ON t.OBJECT_ID = fc.referenced_object_id
WHERE
OBJECT_NAME (f.referenced_object_id) = @TableName
这将 return 所需的外键,但如上所述,我遇到以下结果的问题:
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([PatientCode]) REFERENCES [dbo].[TreatmentPlans] ([PatientCode]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([TPNumber]) REFERENCES [dbo].[TreatmentPlans] ([TPNumber]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
我需要的输出应该是这样的:
ALTER TABLE [dbo].[TreatmentPlanItems] WITH CHECK ADD CONSTRAINT [FK_TreatmentPlanItems_TPNumber] FOREIGN KEY([Patientcode],[TPNumber]) REFERENCES [dbo].[TreatmentPlans] ([Patientcode],[TPNumber]) ALTER TABLE [dbo].[TreatmentPlanItems] CHECK CONSTRAINT [FK_TreatmentPlanItems_TPNumber]
如有任何帮助,我们将不胜感激。
谢谢
下面是代码示例,希望您能根据自己的需要采纳:
declare @tName sysname;
set @tName = 'dbo.TableName';
with vPKColumns as (
select c.object_id, c.column_id, c.name, ixc.key_ordinal
from sys.key_constraints pk
join sys.index_columns ixc on ixc.object_id = pk.parent_object_id and ixc.index_id = pk.unique_index_id
join sys.columns c on c.object_id = pk.parent_object_id and c.column_id = ixc.column_id
where pk.parent_object_id = object_id(@tName) and pk.type = 'PK'
),
vFKs as (
select
quotename(fk.name) as name,
fk.parent_object_id,
fk.object_id,
case
when fk.delete_referential_action_desc collate database_default = 'NO_ACTION' then NULL
else ' on delete ' + replace(lower(FK.delete_referential_action_desc) collate database_default, '_', ' ')
end as onDelete,
case
when fk.update_referential_action_desc collate database_default = 'NO_ACTION' then NULL
else ' on update ' + replace(lower(FK.update_referential_action_desc) collate database_default, '_', ' ')
end as onUpdate
from sys.foreign_keys fk
where exists (
select 1
from sys.foreign_key_columns fkc
join vPKColumns pkc on pkc.object_id = fkc.referenced_object_id and pkc.column_id = fkc.referenced_column_id
where fkc.referenced_object_id = fk.referenced_object_id
)
)
select
'alter table ' + quotename(s.name) + '.' + quotename(t.name) + '
with nocheck add constraint ' + fk.name + ' foreign key (' + stuff(
(select ', ' + quotename(c.name)
from sys.foreign_key_columns fkc
join sys.columns c on c.object_id = fkc.parent_object_id and c.object_id = fkc.parent_object_id and c.column_id = fkc.parent_column_id
where fkc.constraint_object_id = fk.object_id
order by fkc.constraint_column_id
for xml path(''), type).value('text()[1]','nvarchar(max)'),1,2,'') + ') references ' + @tName + ' (' +
stuff(
(select ', ' + quotename(pkc.name)
from vPKColumns pkc
order by pkc.key_ordinal
for xml path(''), type).value('text()[1]','nvarchar(max)'),1,2,'') + ')' +
isnull('
' + onDelete, '') +
isnull('
' + onUpdate, '') + ';
GO
alter table ' + quotename(s.name) + '.' + quotename(t.name) + '
check constraint ' + fk.name + ';
GO'
from vFKs fk
join sys.tables t on t.object_id = fk.parent_object_id
join sys.schemas s on s.schema_id = t.schema_id
order by s.name, t.name, fk.name;