MySQL ON DUPLICATE插入另一个表

时间:2017-02-19 20:39:02

标签: mysql on-duplicate-key

我有以下问题: 每个作者都有此名称的名称和n个别名。每个别名都来自一个来源。每个别名都有m个来源。例如

AUTHOR| ALIAS | SOURCE
-------------------------
Will| Willy |George
Will| Bill  | Jenny
William| Will|  Francis
William| Bill| Maya

我有一张表给作者和他的名字,一张表用于他的所有别名:

CREATE TABLE alias (
    authors_id INT NOT NULL,
    alias VARCHAR(150) NOT NULL,
    id INT NOT NULL AUTO_INCREMENT
    PRIMARY KEY (author_id,alias);

id用作外键。 这是源的第二个表

CREATE TABLE alias_source (
    id INT NOT NULL AUTO_INCREMENT
    source VARCHAR(150) NOT NULL,
    alias_id INT NOT NULL,
    PRIMARY KEY (id)
    FOREIGN KEY (alias_id) REFERENCES alias(id);

现在我需要一个MySQL插入语句来插入 作者,别名,源代码将源插入alias_source。 并且在重复别名上不仅添加了新的源。

1 个答案:

答案 0 :(得分:0)

SQL中的INSERT语句只能插入一个表中,并且只能列出该表的列。您无法在INSERT语句中包含source列,因为它不是alias表的列。

触发器可以允许您插入辅助表,但触发器需要知道要插入的值。在这种情况下,触发器无法获取source的值。

这是一个使用两个INSERT语句更容易完成的任务。

INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
INSERT INTO alias_source ...

但是您遇到问题,因为您的alias表格有一个自动增量列id,但此列不是键的一部分。在InnoDB中,必须将自动增量列设置为键的第一列。

您的alias_source表的外键引用alias(id),但不允许这样做。外键必须引用父表的键。它应该引用唯一键或主键,并且应该引用键的所有列(否则你在子表中得到一行可能引用父表中的多行,这没有意义)。

如果要为alias表使用自动增量列,请将其设为主键,并在其他列上添加辅助UNIQUE约束。

CREATE TABLE alias (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    authors_id INT NOT NULL,
    alias VARCHAR(150) NOT NULL,
    UNIQUE KEY (author_id,alias));

然后在插入后查询id。无论您是插入新行还是已存在的行,您都会获得包含所选作者和别名的行的id

INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
SELECT id FROM alias WHERE author_id = ? AND alias = ? INTO @id;
INSERT INTO alias_source SET alias_id = @id, source = ?; 

在评论中重新提出你的后续问题:

好主意,但它没有像你想象的那样工作。您可以执行id=id的虚拟集合,并将会话变量设置为副作用。

mysql> insert into alias set author_id=1, alias='alias' 
    on duplicate key update id = @id:=id;

mysql> select @id;
+------+
| @id  |
+------+
| NULL |
+------+

但为什么没有将会话变量设置为id?因为此插入重复,所以它是一个新行。因此,在IODKU执行时,自动递增尚未生成id值。

如果您随后对 重复的行执行相同的IODKU,则id值先前已添加到该行中,因此您可以获得副作用中的值:

mysql> insert into alias set author_id=1, alias='alias' 
    on duplicate key update id = @id:=id;

mysql> select @id;
+------+
| @id  |
+------+
|    1 |
+------+

因此,您必须编写应用程序代码以检查@id是否为NULL,如果SELECT id为NULL,则执行@id查询。

这似乎比SELECT id作为INSERT IGNORE之后的标准操作更复杂,如上所示。