0

我有一个用于 MySQL 的软件升级脚本。

此升级的一部分涉及在表中为预先存在的实体创建行(新版本的软件为新的“父”实体创建了一个额外的关联实体,而旧版本没有,所以我必须手动创建它们) . 子实体 ID 是根据命名约定而不是自动增量代理键组成的。

所以我正在写这个匿名查询:

INSERT INTO CHILD_ENTITIES (CHILD_ID, DESCRIPTION, OBJECT_TYPE)
(SELECT 
    CONCAT('PRE_', PARENT_ID, '_SUFF') AS CHILD_ID,
    CONCAT('DESCRIPTION FOR ', PARENT_NAME) AS DESCRIPTION,
    'SYSTEM' AS OBJECT_TYPE
FROM
    PARENT_ENTITIES
WHERE
    CHILD_ID NOT IN (SELECT 
            CHILD_ID
        FROM
            CHILD_ENTITIES));

表结构

CREATE TABLE `CHILD_ENTITIES` (
  `CHILD_ID` varchar(50) NOT NULL,
  `DESCRIPTION` varchar(200) DEFAULT NULL,
  `OBJECT_TYPE` varchar(20) NOT NULL,
  PRIMARY KEY (`CHILD_ID`)
)

该查询应该从父表中选择所有父实体,操作行以获得子实体的三个唯一列(注意没有FK约束,这是由于DB设计造成的),然后将它们插入到子实体中。对于每个父母,应该创建一个新的孩子。该WHERE子句是一个预防性声明,实际上是为了避免重复而编写的,但即使没有,查询仍然应该在正常设置中不会失败WHERE(因为这些 ID 是通过约定生成的,并且从未手动插入)。

问题是查询MySQL 5.1.69-community按预期工作正常,但是当运行时5.6.10(使用 Navicat,如果这很重要)它的行为不同:当父实体存在时不插入记录。

通过几次尝试分析查询,我发现WHERE CHILD ID NOT IN ( SELECT CHILD_ID...被误解了,指的是子查询的列而不是父选择的列。如果我稍微改变查询

SELECT 
    CONCAT('PRE_', PARENT_ID, '_SUFF') AS CHILD_ID,
    CONCAT('DESCRIPTION FOR ', PARENT_NAME) AS DESCRIPTION,
    'SYSTEM' AS OBJECT_TYPE
FROM
    PARENT_ENTITIES
WHERE
    CHILD_ID NOT IN (SELECT 
            CHILD_ID AS DUMMY
        FROM
            CHILD_ENTITIES);

结果:Unknown column 'CHILD_ID' in 'IN/ALL/ANY subquery'

该错误发生在两个版本的 MySQL 上。

那么,我应该如何进行这样的查询以从父 ID 开始填充子实体?

4

1 回答 1

2

我建议您在所有列中添加表前缀,然后重试:

INSERT INTO CHILD_ENTITIES (CHILD_ID, DESCRIPTION, OBJECT_TYPE)
SELECT 
    CONCAT('PRE_', p.PARENT_ID, '_SUFF') AS CHILD_ID,
    CONCAT('DESCRIPTION FOR ', p.PARENT_NAME) AS DESCRIPTION,
    'SYSTEM' AS OBJECT_TYPE
FROM
    PARENT_ENTITIES AS p
WHERE
    p.CHILD_ID NOT IN (SELECT 
            c.CHILD_ID
        FROM
            CHILD_ENTITIES AS c);

如果这也因错误而失败,那么它可能是一个错误。升级到最新(5.6.13)版本,看看错误是否仍然存在。


再次阅读查询,我看不出它将如何避免重复。也许你打算这样写?

---
WHERE
    CONCAT('PRE_', p.PARENT_ID, '_SUFF') NOT IN (SELECT 
            c.CHILD_ID
        FROM
            CHILD_ENTITIES AS c);
于 2013-09-02T10:32:28.840 回答