2012-03-09 92 views
1

我被赋予创建存储过程以复制与数据库中给定ID关联的每一条数据的任务。这些数据跨越数十个表格。每个表可能有几十个匹配的行。SQL按照PK FK关系从多个表中递归复制行

例如:

表帐户
PK =帐户ID

表AccountSettings
FK =帐户ID

表用户
PK =用户名
FK =帐户ID

表UserContent
PK = UserContentID
FK =用户名

我想创建与一个帐户ID(这将穿越几乎所有表)副本将有一个新的帐户ID和UserContentID但具有相同的用户ID相关联的所有内容的副本。新数据需要在各自的表格中。 :)好玩吗?

以上只是一个示例,但我会为50或60表做类似的工作。 我已经使用CTE进行了研究,但对它们仍然有点模糊。这可能被证明是最好的方法。我的SQL技能是......好吧,我已经使用它约40个记录小时到目前为止:)

任何意见或方向在哪里看,将不胜感激。另外,如果可能或者更好,我不会反对通过C#来做到这一点。

在此先感谢您的任何帮助信息。

+0

在您的示例中,1帐户可以有0-n个用户,但** 1个用户只能有0-1个帐户** =>第二个帐户将不可能具有相同的用户ID(如果您当然不想删除用户连接到第一个帐户) – Aprillion 2012-03-09 22:55:47

+0

哇。我不会这样做。 CTE只会递减100次,所以你可以超过这个。为什么不直接添加基于临时表中的表的外键的临时表,直到不添加新行? – saarp 2012-03-11 10:27:02

+0

@saarp:为什么CTE只会缓冲100次?这是一个荒谬的假设。 – 2012-09-07 22:51:13

回答

3

解决这个问题的最简单方法是强力方法:编写一个非常长的proc来处理每个表单独。这将很容易出错并且很难维护。但它的优点是不依赖于数据库或数据库元数据处于任何特别一致的状态。

如果你想要基于元数据的东西,事情会更有趣。您有三个挑战:

  1. 您需要以编程方式标识所有相关的表。
  2. 您需要为所有50或60生成插入语句。
  3. 您需要为远离帐户表超过一个或两个步骤的那些表捕获生成的id,以便它们可以反过来用作外键在更复制的记录中。

我已经在过去看过这个问题,虽然我不能给你一个水密算法,但我可以给你一个通用的启发式。换句话说:我就是这么想的。

  1. 使用MS Entity Framework的更高版本(你说你会开放使用C#),建立一个Account表和所有相关表的模型。
  2. 回顾一下它。如果你的数据库很多,你的应用程序假设的一些关系会出于某种原因而没有在数据库中建立实际的外键关系。无论如何,在你的模型中创建它们。
  3. 在C#中编写一个可以接受Account对象并遍历所有相关表的递归例程。选择几个Account实例,并将表名和关键信息转储到一个文件中。审查完整性和合理性。
  4. 一旦你感到满意,你有一个很好的模型和一个很好的算法来抓取所有的东西,现在是时候破解代码了。您需要编写一个更复杂的算法,它可以读取一个Account并递归地克隆引用它的所有记录。您可能需要反思才能做到这一点,但并不难:您需要的所有元数据都会在某处。
  5. 测试你的代码。留出足够的时间进行调试。
  6. 在第3步中使用您的第一个算法来比较结果的完整性和准确性。

EF方法的优点:随着数据库的变化,你的模型也是如此,如果你的代码是基于元数据的,它应该能够适应。缺点:如果您有像“真正”相同但是不同类型的字段,或者未正确建模的复杂三向关系或需要解析的嵌入式CSV列表等现象出来,这是行不通的。它只适用于你的数据库状态良好且建模良好的情况。否则,你需要诉诸暴力。

+0

谢谢。我最终确定了所有的事情。它相当大的1800线左右,但它工作得很好。保持最新状态将是一件痛苦的事情。感谢您对此的看法。 – user1260249 2013-04-05 20:06:36

+0

+1好的建议。我最终在我的解决方案中使用了EF,这比我最初预期的要容易得多,所以我肯定会推荐使用它。最重要的是,维护甚至扩展要容易得多。 – tfrascaroli 2017-02-20 13:34:21

+0

@tfrascaroli感谢您的荣誉!我很高兴我的建议很有帮助! – 2017-02-20 17:17:39