Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql &引用;插入…选择";具有多个值和规范化数据库的事务_Mysql_Sql_Database_Normalization_Mariadb - Fatal编程技术网

Mysql &引用;插入…选择";具有多个值和规范化数据库的事务

Mysql &引用;插入…选择";具有多个值和规范化数据库的事务,mysql,sql,database,normalization,mariadb,Mysql,Sql,Database,Normalization,Mariadb,正确解释了如何在数据库中同时插入“层次”结构(is-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; 该解决方案在每次插入一个对象时效果良好 但是,

正确解释了如何在数据库中同时插入“层次”结构(is-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通过基类ID将
派生类
的每个实例“链接”到先前创建的
基类

理想情况下,我会同时“循环”两个表,但在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代码(使用游标)


有没有不使用游标解决此问题的方法?

我不能完全确定我是否理解您的问题。我认为您正在尝试将
d0
d1
插入
base\u class
base\u id
d2
,和
d3
以相同的顺序进入
派生类
,这样
基本类
派生类
中插入的第n个值都来自
stuff
中的第n个记录。如果我的理解是正确的,下面的交易将满足您的要求

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

光标应该起作用。您可以在
stuff
表中循环,一次执行一个插入,并在执行过程中获取插入ID。类似这样(未经测试):

另一种可能的方法是在两个“insert”表上创建一个视图。根据表的结构,在插入视图时可能会有限制,但类似的操作可能会起作用(也未测试):


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

如果使用MySQL外部的脚本语言,这可能会容易得多。Python、Ruby甚至NodeJS都可以轻松地处理这种递归。@tadman:是的,最简单的解决方案是使用外部语言。然而,我真的很好奇这是否可以在纯MySQL中实现
base\u id
不是
stuff
表中的一列。对不起,我的解释有点混乱。我想说的是,我有一个对象的层次结构(用面向对象的术语思考)
derived\u class行是从
base\u class
行派生的实例。如果需要创建
派生类
的实例,外键约束会强制我首先创建
基本类
实例,然后将其ID存储在随后创建的
派生类
实例中。当我必须创建一个时很容易,因为我可以使用
LAST\u INSERT\u ID()
。如果我必须创建更多的实例,我没有办法获得所有的新ID。游标似乎确实是解决这个问题的唯一方法。非常酷的特性我再次提出了这个问题,因为我真的很好奇这个问题是否可以在没有过程编程和游标的情况下解决。@VittorioRomeo:你尝试过视图吗?我知道在视图中插入有限制,但这可能值得一试。看看我最新的答案。
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