INSERT + SELECT + ON DUPLICATE KEY with column alias in SELECT 子句

INSERT + SELECT + ON DUPLICATE KEY with column aliases in SELECT clause

当我试图在 SELECT 子句具有列别名的查询中将 INSERT、SELECT 和 ON DUPLICATE KEY 链接在一起时,我遇到了一个相当令人惊讶的障碍。例如,考虑以下情况:

:

CREATE TABLE source ( 
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    v INT NOT NULL
);
INSERT INTO source (v) VALUES (1), (2), (3);
CREATE TABLE dest (
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    v INT NOT NULL
);

假设我正在尝试用 POW(source.v,2) 的值填充 dest.v,而不管 dest 中是否已经存在值。当然,我试过了:

INSERT INTO dest 
    SELECT id, POW(v, 2) AS p FROM source 
    ON DUPLICATE KEY UPDATE dest.v=source.p;

然而,MySQL坚持认为source.p不存在:

ERROR 1054 (42S22): Unknown column 'source.p' in 'field list'

相当不方便,我不得不求助于使用更慢更麻烦的查询:

INSERT INTO dest 
    SELECT * FROM ( 
         SELECT id, POW(v, 2) AS p FROM source 
    ) s
    ON DUPLICATE KEY UPDATE dest.v=s.p;

这与原始查询差别很小,但有效。为什么会这样?

函数的别名只是由mysql计算出来的,可以直接使用。一个不太糟糕的替代查询可能是:

INSERT INTO dest (v) 
    SELECT POW(v, 2) AS p FROM source 
    ON DUPLICATE KEY UPDATE dest.v=POW(v, 2);

(未测试...)

我总是把查询写在下面

INSERT INTO dest ( id, v)
SELECT id, POW(v, 2) AS p FROM source 
ON DUPLICATE KEY UPDATE dest.v=VALUES(v);

VALUES() 避免再次写入相同的表达式。始终尝试指定您要插入的列名称,以防万一您在将来的某个时间向 table 添加新列