【问题标题】:Drop and recreate foreign key referencing multiple columns删除并重新创建引用多列的外键
【发布时间】:2019-09-13 18:07:39
【问题描述】:

我正在尝试使用来自生产服务器的数据刷新开发服务器,但这不能通过直接恢复来完成,因为开发环境包含我们需要保留的不在生产环境中的对象。所以我想做的是截断需要刷新的表,然后插入数据。我为此创建了一个程序,它一直有效,直到我们得到外键。

我继承的数据库写得不是很好,在大多数表中都有几个主键列。我正在查看这个问题Cannot truncate table because it is being referenced by a FOREIGN KEY constraint? 并将@peter-szanto 和@marc-2377 提供的最佳解决方案合并到存储过程中,只要在插入#FKs 中的sys.foreign_key_columns 中有一个唯一约束,它就可以很好地工作.使用脚本会出错

“引用的表中没有主键或候选键”

在某些表上,因为它们引用具有多个主键列作为一个外键的表。

代码原样返回这些以重新创建表FK_stmnt中的fks

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY([fk1]) REFERENCES [dbo].[othertable] ([pk1])

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY([fk2]) REFERENCES [dbo].[othertable] ([pk2])

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY([fk3]) REFERENCES [dbo].[othertable] ([pk3])

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY([fk4]) REFERENCES [dbo].[othertable] ([pk4])

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY([fk5]) REFERENCES [dbo].[othertable] ([pk5])

需要返回结果为

ALTER TABLE [dbo].[sometable] WITH NOCHECK 
    ADD CONSTRAINT [sometable$othertable__12345] 
        FOREIGN KEY ([fk1], [fk2], [fk3], [fk4], [fk5]) 
            REFERENCES [dbo].[othertable] ([pk1], [pk2], [pk3], [pk4], [pk5])

即对于每个 sometable$othertable__12345 约束将列组合在一个语句中。

有什么想法吗?

【问题讨论】:

  • 复合键(包括主键)只要满足业务需求就可以。
  • 可以,只要它们满足业务需求。但这实际上是一个到处都有重复数据的数据库的巨大噩梦,因此几乎每个表上的复合键都带有 fk

标签: sql tsql foreign-keys truncate composite-key


【解决方案1】:

以下 SQL 将列出所有 FK、表名、FK 键、引用的表和引用的键……如果有多个键,则为逗号分隔列表。

这只是我的库存工具包中的 SQL,并没有真正针对您的确切问题量身定制,但您应该能够对其进行调整以供您使用以生成所需的内容。

 SELECT fkeys.[name] AS FKName, 
        OBJECT_NAME(fkeys.parent_object_id) AS TableName,
        (SELECT STUFF((SELECT ',' + c.[name]
         FROM sys.foreign_keys fk INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id
              INNER JOIN sys.columns as c ON t.object_id = c.object_id
              INNER JOIN sys.foreign_key_columns AS fc ON c.column_id = fc.parent_column_id 
                                                      AND fc.constraint_object_id = fk.object_id 
                                                      AND fc.parent_object_id = fk.parent_object_id 
        WHERE fk.[name] = fkeys.[name]
        FOR XML PATH ('')), 1, 1, '')) AS FKFolumns,
        OBJECT_NAME(fkeys.referenced_object_id) AS ReferencedTableName,
        (SELECT STUFF((SELECT ',' + c.[name]
         FROM sys.foreign_keys fk INNER JOIN sys.tables t ON fk.referenced_object_id = t.object_id
              INNER JOIN sys.columns as c ON t.object_id = c.object_id
              INNER JOIN sys.foreign_key_columns AS fc ON c.column_id = fc.referenced_column_id 
                                                      AND fc.constraint_object_id = fk.object_id 
                                                      AND fc.referenced_object_id = fk.referenced_object_id 
        WHERE fk.[name] = fkeys.[name]
        FOR XML PATH ('')), 1, 1, '')) AS ReferencedFKFolumns
   FROM sys.foreign_keys fkeys
  ORDER BY FKName;

【讨论】:

  • AND c.column_id = fc.parent_column_id 这对我来说失败了,因为 fc.parent_column_id 有时与父级中的列 id 不同:T(u,obj); Pairs(u,o1,o2, fk1 (u,o1) ref T(u,obj), fk2(u,o2) ref T(u,obj) 这里 Pairs 中的 3 列@T 中的 2 列。跨度>
  • 我不确定我是否理解...一个 FK 如何将 3 列关联到 2 列?它不能。它们必须匹配。
  • 是的,他们可以有 2 个 FK,请参阅评论中的示例,这是合法的 sql。
  • 哦,我想我明白你在说什么了。我的版本中有一个复制粘贴错误。它应该是referenced_column_id。我会更新答案。
  • 这看起来很有用,但由于某种原因,盒子似乎在 ReferencedFKFolumns 中随机返回了许多空值。
【解决方案2】:

要让一个表中的多个列与另一个表的多个列具有 fk 关系,此语法有效:

alter table dbo.x
    add constraint FK_A foreign key ([SalesOrderID] ,[SalesOrderDetailID])
        references dbo.y1 ([SalesOrderID] , [SalesOrderDetailID])

在表 dbo.y1 中,两列是 dbo.y1 上的主键。

【讨论】:

  • 问题是如何让 FK const 已经在表中,而不是如何创建它们。谢谢
猜你喜欢
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多