【问题标题】:How can I dump data from tables with composite PK/FKs into similar tables Using ID/FK如何使用 ID/FK 将具有复合 PK/FK 的表中的数据转储到类似的表中
【发布时间】:2018-12-08 03:05:10
【问题描述】:

假设我有一个需要复合 PK 的表:

Table1
+---------+---------+
|  CompA  |  CompB  |
+---------+---------+
| Value 1 | Value 2 |
| Value 1 | Value 3 |
| Value 2 | Value 3 |
+---------+---------+

然后我构建了第二个表,并希望在这个新的表 2 中使用表 1 中的 PK 作为 FK。有两种方法可以做到这一点。

选项 1 - 我最初选择的选项是仅使用表 1 中的复合键作为表 2 中的 FK。

Table 2
+------+---------+---------+
| T2PK |  CompA  |  CompB  |
+------+---------+---------+
| A    | Value 1 | Value 2 |
| B    | Value 1 | Value 3 |
| C    | Value 2 | Value 3 |
| D    | Value 2 | Value 3 |
+------+---------+---------+

选项 2 - 我现在要过渡到的选项是将表 1 中的 PK 更改为 ID 列,并对值对施加复合 UNIQUE 约束

Table 1
+----+---------+---------+
| ID |  CompA  |  CompB  |
+----+---------+---------+
|  1 | Value 1 | Value 2 |
|  2 | Value 1 | Value 3 |
|  3 | Value 2 | Value 3 |
+----+---------+---------+

因此,现在,在您想要使用表 1 作为 FK 的任何其他表中,您引用单个 ID 列(因为现在是表 1 的 PK)

Table 2
+----+------+
| PK | T1FK |
+----+------+
| A  |    1 |
| B  |    2 |
| C  |    3 |
| D  |    3 |
+----+------+

问题 - 我最初使用选项 1 构建表。为 1 个实体拥有跨越多个列的 FK 变得很烦人,并且使我的连接语句比它们需要的更复杂。我现在想过渡到选项 2。我已经使用选项 2 的方法构建了表,但是我想不出一个很好的方法来将选项 1 表的数据转储到我的新选项 2 表中。我不知道如何将Table1, Option1 的数据转储到Table1 Option2 的表中并生成ID,如何将这些生成的ID 与Table2 Option1 的同一组数据绑定到新的Table2 Option2

【问题讨论】:

标签: sql oracle


【解决方案1】:

假设我们有这些“旧”表:

CREATE TABLE Table1(
  CompA varchar2(10), CompB  varchar2(10), constraint Table1_pk primary key(CompA,CompB)
);

Insert all
into Table1 values('Value 1', 'Value 2')
into Table1 values('Value 1', 'Value 3')
into Table1 values('Value 2', 'Value 3')
SELECT null FROM dual;

CREATE TABLE Table2(
  T2PK varchar2(1),
  CompA varchar2(10), CompB  varchar2(10), 
  constraint Table2_fk foreign key(CompA,CompB) references table1(CompA,CompB)
);

Insert all
into Table2 values('A', 'Value 1', 'Value 2')
into Table2 values('B', 'Value 1', 'Value 3')
into Table2 values('C', 'Value 2', 'Value 3')
into Table2 values('D', 'Value 2', 'Value 3')
SELECT null FROM dual;

我们可以使用以下代码迁移到“新”表:

CREATE TABLE new_Table1(
   ID int PRIMARY KEY,
   CompA varchar2(10), CompB  varchar2(10), 
   constraint new_Table1_uq unique(CompA,CompB)
);

INSERT INTO new_Table1( id, CompA, CompB)
SELECT rownum, CompA, CompB FROM Table1;

CREATE TABLE new_Table2(
   PK  varchar2(1),
   T1FK int,
   constraint new_Table2_fk foreign key(T1FK) references new_Table1( id )
);

INSERT INTO new_Table2( PK , T1FK )
SELECT t2.T2PK, t1.ID
FROM Table2 t2
JOIN new_Table1 t1 
ON t2.CompA = t1.CompA AND t2.CompB = t1.CompB;

这是一个工作演示:https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=32e852ab929c9431cce31495745ec6ba

【讨论】:

  • 不怪你没有早点回答,因为 SO 答案本质上是利他的(IMO),但上帝希望我早点看到这个。我自己想出了一个更糟糕的解决方案,在旧表和新表之间使用 DISGUSTING 连接,但这个解决方案非常优雅。谢谢,如果我发现自己在相同的情况下,我将在未来使用它。
  • @Rosey 。 . .这与我之前发布的答案基本相同。我的意思是,演示是一个很好的补充,但你的评论很奇怪。
【解决方案2】:

好吧,您可以使用row_number() 或rownum 来分配id:

create table new_table1 as
    select rownum as table1_id, compA, compB
    from table1;

然后您可以将其用作:

create table new_table2 as
    select t2.id, t2.table1_id
    from table2 t2 left join  -- outer join just in case you have NULL values
         new_table1 t1
         on t2.compA = t1.compA and t2.compB = t1.compB;

【讨论】:

  • 我认为要向 OP 提及的重要一点是他们必须重新编号并保留原始密钥,至少在迁移期间是这样。他们的主要问题是他们试图在没有旧键的情况下创建新表,这使他们无法为第二个表提供参考
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多