将csv加载到多个表以解决关键约束问题

zbwhf8kr  于 2021-06-20  发布在  Mysql
关注(0)|答案(4)|浏览(292)

在mysql中,是否可以将一个csv加载到一个存储过程中,该存储过程将依次填充多个表,每个表都具有外键依赖项exl-table1的主键将在table2中使用,table2的主键将在table3中使用?
示例—存储过程中要读取的具有5列的单个文件,在csv文件中的每一行/每条记录中,使用column1和column2在表1中插入,获取主键,然后在表2中插入第3列和第4列,获取主键并使用table1的主键和table2的主键以及coulmn5在表3中插入
我正在考虑下列方案-
有一个外部应用程序,它读取csv,并将数据[csv中的每一行]传递给带有prepare语句的存储过程,该语句将负责随后插入到所需的表中。
将csv加载到一个temp表中,并有一个带有prepare语句的存储过程,它将负责随后插入到所需的表中。
有一个读取csv的外部应用程序,并有一组准备好的语句插入到后续的表中。但是,从外部获取primarykey然后重新使用会导致延迟。。
重新措辞的问题,以了解性能有效的方法来解决这个问题,如果有可能加载csv,我们怎么做?

o2gm4chl

o2gm4chl1#

有一个解决办法。你可以使用一些辅助触发器。假设您将数据(或从文件加载)插入主表。然后是表1(c1,c2),表2(c3,c4)和表3(c5),就像你的问题一样。
现在:
我们在主表上使用trigger1将数据插入表1。某些会话变量用于存储临时字段值。
我们在table1表上使用trigger2将数据插入table2
我们在table2表上使用trigger3将数据插入table3
让我们看看剧本:

CREATE TABLE main (
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL
)
ENGINE = INNODB;

CREATE TABLE table1 (
  id int(11) NOT NULL AUTO_INCREMENT,
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 10;

CREATE TABLE table2 (
  id int(11) NOT NULL AUTO_INCREMENT,
  id_ref_table1 int(11) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB
AUTO_INCREMENT = 20;

CREATE TABLE table3 (
  id int(11) NOT NULL AUTO_INCREMENT,
  id_ref_table2 int(11) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB;

CREATE TABLE main (
  c1 varchar(255) DEFAULT NULL,
  c2 varchar(255) DEFAULT NULL,
  c3 varchar(255) DEFAULT NULL,
  c4 varchar(255) DEFAULT NULL,
  c5 varchar(255) DEFAULT NULL
)
ENGINE = INNODB,
AUTO_INCREMENT = 30;

DELIMITER $$

CREATE TRIGGER trigger1
AFTER INSERT
ON main
FOR EACH ROW
BEGIN
  SET @c3 = NEW.c3;
  SET @c4 = NEW.c4;
  SET @c5 = NEW.c5;

  INSERT INTO table1 (c1, c2)
    VALUES (NEW.c1, NEW.c2);
END
$$

CREATE TRIGGER trigger2
AFTER INSERT
ON table1
FOR EACH ROW
BEGIN
  INSERT INTO table2 (id_ref_table1, c3, c4)
    VALUES (NEW.id, @c3, @c4);
END
$$

CREATE TRIGGER trigger3
AFTER INSERT
ON table2
FOR EACH ROW
BEGIN
  INSERT INTO table3 (id_ref_table2, c5)
    VALUES (NEW.id, @c5);
END
$$

DELIMITER ;

以及一些带有结果的insert语句:

INSERT INTO main(c1, c2, c3, c4, c5) VALUES
('1', '2', '3', '4', '5'),
('11', '22', '33', '44', '55');

SELECT id, c1, c2 FROM table1;
------------------------------
10  1   2
11  11  22

SELECT id, id_ref_table1, c3, c4 FROM table2;
---------------------------------------------
20  10  3   4
21  11  33  44

SELECT id, id_ref_table2, c5 FROM table3;
-----------------------------------------
30  20  5
31  21  55
dy2hfwbg

dy2hfwbg2#

否,请参阅附录c1—存储程序的限制,它告诉您在存储例程中不能使用加载数据。
存储例程中不允许使用sql语句
存储例程不能包含任意sql语句。不允许使用以下语句:
locking语句锁定表和解锁表。
改变观点。
加载数据和加载表。
同样,在准备好的语句的文档中,您会发现它说明了以下内容
一般来说,sql准备语句中不允许的语句在存储程序中也不允许。
然后给出一个有用的允许语句列表。不幸的是,您在存储程序的文档中找不到相同的列表(它可能更有用)。

ybzsozfc

ybzsozfc3#

经过上述多种方法,找到了一种最佳的方法。将整个任务分为两个主要部分—拆分数据和加载表
split—将源文件拆分为多个CSV的外部应用程序[匹配表1、表2和表3的架构]
加载-使用加载数据填充,这是填充表的最快方法。
[对于所有这些表,硬编码主键而不是依赖于自动增量]
谢谢大家的意见、建议和指导。

7gs2gvoe

7gs2gvoe4#

是的,可以做到。我不认为应该这样做,因为这样会将大量的业务逻辑放入数据库,而这通常被认为是一件坏事。这在数据库之外的应用程序中更容易和更好地完成。
但是-问题是它能不能做到。我可以通过将csv加载到一个临时表中来实现这一点(因为在存储过程中似乎没有逐行读取的方法)。然后可以遍历表中的所有行并执行需要执行的操作。
希望这能给你一个线索让你走。

相关问题