【问题标题】:insert into a table from another table when a new record is inserted插入新记录时从另一个表插入到一个表中
【发布时间】:2017-08-01 05:16:25
【问题描述】:

我有 2 个表,如果记录不存在,我想将第一个表中的所有记录插入到第二个表中。如果将新行添加到第一个表中,则必须将其插入到第二个表中。

我找到了这个查询 INSERT INTO Table2 SELECT * FROM Table1 WHERE NOT EXISTS (SELECT * FROM Table2) 但如果向 table1 添加新行,则不会将行插入 table2。

PS:table1 和 table2 字段相同,包含数千条记录

【问题讨论】:

  • 您是否正在寻找一种在 Python 中执行此操作的方法?因为这看起来像是 MySQL/PostgreSQL/...中的触发器的工作...
  • 我正在使用 python 连接到数据库,问题是我不知道会执行此操作的查询。我找到了这个解决方案:'insert into Table2 select * from table1 where not exists (select * from Table2)',但是如果将新记录添加到 table1,它不会插入到 table2 中。 !!!
  • 您使用的是什么 SQL 数据库? Afaik 触发器不是标准 SQL,因此它是否可以完成取决于您的数据库系统。
  • 我正在使用access数据库
  • 查看触发器。

标签: python sql


【解决方案1】:

您可以在 SQL 中完成所有操作 - 例如,如果您可以每 2 分钟运行一次批处理...

-- with these two tables and their contents ...
DROP TABLE IF EXISTS tableA;
CREATE TABLE IF NOT EXISTS tableA(id,name,dob) AS (
          SELECT 42,'Arthur Dent',DATE '1957-04-22'
UNION ALL SELECT 43,'Ford Prefect',DATE '1900-08-01'
UNION ALL SELECT 44,'Tricia McMillan',DATE '1959-03-07'
UNION ALL SELECT 45,'Zaphod Beeblebrox',DATE '1900-02-01'
);
ALTER TABLE tableA ADD CONSTRAINT pk_A PRIMARY KEY(id);

DROP TABLE IF EXISTS tableB;
CREATE TABLE IF NOT EXISTS tableB(id,name,dob) AS (
          SELECT 43,'Ford Prefect',DATE '1900-08-01'
UNION ALL SELECT 44,'Tricia McMillan',DATE '1959-03-07'
UNION ALL SELECT 45,'Zaphod Beeblebrox',DATE '1900-02-01'
);
ALTER TABLE tableB ADD CONSTRAINT pk_B PRIMARY KEY(id);

-- .. this MERGE statement will ad the row with id=42 to table B ..

MERGE
INTO tableB t
USING tableA s
 ON s.id   = t.id
WHEN NOT MATCHED THEN INSERT (
  id
, name
, dob
) VALUES (
  s.id
, s.name
, s.dob
);

【讨论】:

  • 这不是触发器。 OP已经提到将table1的内容复制到table2。问题是他们想要一个触发器:每次将一行添加到 table1 时主动地将该行添加到 table2。
  • 最初的提问者没有提到触发器。并且“如果记录不存在,则将第一个表中的所有记录插入到第二个表中”实际上使我远离触发器。让我们等待提问者说什么......
  • 问题的最后一行是“如果在第一个表中添加新行,则必须将其插入到第二个表中。”。你怎么能不把它解释为一个触发器?
  • @WillemVanOnsem 是的,我想要一些东西,每次将一行添加到表中时,也会将该行添加到 table2。我不知道触发器是什么!!
  • 轮到你了,威廉
【解决方案2】:

所以它是一个 Access 数据库。

运气不好。它们没有触发器。

那好吧。我想你知道如何使用 Python 在 Access 中插入一行,所以我不会介绍。

我将在插入一行后构建一个场景。

CREATE TABLE tableA (
  id   INTEGER
, name VARCHAR(20)
, dob  DATE
, PRIMARY KEY  (id)
)
;
INSERT INTO tableA(id,name,dob) VALUES(42,'Arthur Dent','1957-04-22');
INSERT INTO tableA(id,name,dob) VALUES(43,'Ford Prefect','1900-08-01');
INSERT INTO tableA(id,name,dob) VALUES(44,'Tricia McMillan','1959-03-07');
INSERT INTO tableA(id,name,dob) VALUES(45,'Zaphod Beeblebrox','1900-02-01');

CREATE TABLE tableB (
  id   INTEGER
, name VARCHAR(20)
, dob  DATE
, PRIMARY KEY  (id)
)
;
INSERT INTO tableB(id,name,dob) VALUES(43,'Ford Prefect','1900-08-01');
INSERT INTO tableB(id,name,dob) VALUES(44,'Tricia McMillan','1959-03-07');
INSERT INTO tableB(id,name,dob) VALUES(45,'Zaphod Beeblebrox','1900-02-01');

好的。场景准备好了。

合并 ....

MERGE
INTO tableB t
USING tableA s
 ON s.id   = t.id
WHEN NOT MATCHED THEN INSERT (
  id
, name
, dob
) VALUES (
  s.id
, s.name
, s.dob
);

42000:1:-3500:[Microsoft][ODBC Microsoft Access Driver] 
Invalid SQL statement; 
expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'.

所以,不支持合并。

尝试其他方法:

INSERT INTO tableB
SELECT * FROM tableA
WHERE id <> ALL (SELECT id FROM tableB)
;

1 row inserted

或者:

-- UNDO the previous insert
DELETE FROM tableB WHERE id=42;
1 row deleted
-- retry ...
INSERT INTO tableB
SELECT * FROM tableA
WHERE id NOT IN (SELECT id FROM tableB)
;
1 row inserted

你可以像上面一样运行它。

或者,如果您从 Python 插入表 A 是:

INSERT INTO tableA(id,name,dob) VALUES(?,?,?);

...并且您通过主机变量提供了 id、name 和 dob 的值, 你可以继续:

INSERT INTO tableB 
SELECT * FROM tableA a 
WHERE id=? 
  AND NOT EXISTS(
   SELECT * FROM tableB WHERE id=a.id
  );

第一个宿主变量中的值仍然是 42,并且可以重复使用它。在单行插入的情况下,这种方式会更快。

如果您执行批量插入,那么,我会将所有新行插入表 A,然后运行 ​​INSERT ... WHERE ... NOT ININSERT ... WHERE id &lt;&gt; ALL ....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多