“插入...选择”具有多个值和规范化数据库的事务

时间:2015-02-20 20:08:46

标签: mysql sql database normalization mariadb

This question正确地解释了如何在数据库中同时插入数据以实现" hierarchical"结构(是-a 关系):

  

不,您无法在一个MySQL命令中插入多个表。您   但是可以使用交易。

BEGIN;
INSERT INTO base_class (data0, data1) VALUES('0', '1');
INSERT INTO derived_class (base_id, data2, data3) VALUES(LAST_INSERT_ID(), '2', '3');
COMMIT;

当一次插入一个东西时,解决方案很有效。

但是,我需要使用INSERT...SELECT同时插入多个值。

BEGIN;
INSERT INTO base_class (data0, data1) SELECT d0, d1 FROM stuff
INSERT INTO derived_class (base_ids, data2, data3) SELECT ???, d2, d3 FROM stuff
COMMIT;

我该如何告诉MySQL" link"通过基类ID,先前创建的derived_class的每个base_class实例?

理想情况下,我会"循环"同时通过这两个表,但在MySQL或MariaDB中这是不可能的:

# PSEUDOCODE! NOT VALID.
BEGIN;
INSERT INTO 
                base_class (data0, data1) 
     ALONG_WITH derived_class (base_ids, data2, data3)   
     SELECT d0, d1, GET_ALONG_FIELD(base_class, id), d2, d3 FROM stuff
     #      _______ table 1 values
     #              _______________________________________ table 2 values
COMMIT;

如何在保持"层次结构的同时解决这个问题?我桌子的设计?


编辑:

我再次打开了这个问题,因为我很好奇是否有可能实现我想要的行为,而不必使用类似程序的SQL代码(使用游标)。

有没有办法在不使用游标的情况下解决此问题?

2 个答案:

答案 0 :(得分:2)

游标应该做到这一点。您可以遍历stuff表并一次执行一次插入,随时获取插入ID。像这样(未经测试):

BEGIN;

  DECLARE get_stuff CURSOR FOR SELECT id FROM stuff;
  DECLARE current_id INT;

  OPEN get_stuff;
  insert_stuff: LOOP

    FETCH get_stuff INTO current_id;
    INSERT INTO base_class (data0, data1)
      SELECT d0, d1 FROM stuff WHERE id = current_id
    INSERT INTO derived_class (base_ids, data2, data3)
      SELECT mysql_insert_id(), d2, d3 FROM stuff WHERE id = current_id

  END LOOP insert_stuff;
  CLOSE get_stuff;

COMMIT;

另一种可能的方法是在两个"插入"上创建一个视图。表。根据表的结构方式插入视图可能存在限制,但这样的事情可能有效(也未经过测试):

CREATE VIEW stuff_view AS
  SELECT b.data0, b.data1, d.data2, d.data3 FROM base_class AS b
  INNER JOIN dervied_class AS d ON (d.base_id = b.id)

INSERT INTO stuff_view (data0, data1, data2, data3)
  SELECT d0, d1, d2, d3 FROM stuff

我实际上不确定MySQL是否会自动为基本类和派生类表分配适当的ID。

答案 1 :(得分:0)

我不完全确定我理解你的问题。我认为您正在尝试将d0d1插入base_classbase_idsd2d3到{{1}以相同的顺序,以便derived_classbase_class中的第n个插入值都来自derived_class中的第n个记录。如果我的理解是正确的,那么以下交易就会做你想要的。

stuff