Upsert(合并)用于更新记录(如果存在),否则插入

Posted

技术标签:

【中文标题】Upsert(合并)用于更新记录(如果存在),否则插入【英文标题】:Upsert (merge) for updating record if it exists and inserting otherwise 【发布时间】:2022-01-09 21:55:24 【问题描述】:

我正在尝试编写一个 DB2 查询,该查询允许我更新已存在的记录,但如果它不存在,则应插入它。我编写了以下查询来完成此操作:

MERGE INTO OA1P.TLZ712A1 AS PC
USING (
    SELECT * FROM OA1P.TLZ712A1 
    WHERE CALENDAR_ID=13 AND 
    "PACKAGE"='M2108'
) PC2
ON (PC.ID_PACKAGE_CALENDAR=PC2.ID_PACKAGE_CALENDAR)
WHEN MATCHED THEN 
    UPDATE SET ACT_DATE = '31.12.2021'
WHEN NOT MATCHED THEN 
    INSERT ("PACKAGE", ACT_DATE, CALENDAR_ID, PREPTA, MIXED) VALUES ('M2108', '31.12.2021', 13, 0, 0)

此查询应尝试检查是否已存在符合选择条件的记录。更新记录似乎工作正常,但我无法让“WHEN NOT MATCHED”部分工作并插入新记录。谁能提供一些帮助?

该表用于保存某个软件包的激活日期。 PACKAGE 是对包含包名称的包表的引用(例如“M2108”)。 CALENDAR_ID 是指将激活软件包的系统。实际日期存储在ACT_DATE

没有设法将 DDL 放入 SQLFiddle,所以我必须在此处提供:

CREATE TABLE OA1P.TLZ712A1 (
    ID_PACKAGE_CALENDAR INTEGER DEFAULT IDENTITY GENERATED BY DEFAULT NOT NULL,
    CALENDAR_ID INTEGER,
    "PACKAGE" VARCHAR(10) NOT NULL,
    ACT_DATE DATE NOT NULL,
    PREPTA SMALLINT DEFAULT 0 NOT NULL,
    MIXED SMALLINT DEFAULT 0 NOT NULL,
    "COMMENT" VARCHAR(60) NOT NULL,
    LAST_MODIFIED_PID CHAR(7) NOT NULL,
    ST_STARTID TIMESTAMP NOT NULL,
    ST_FROM TIMESTAMP NOT NULL,
    ST_TO TIMESTAMP NOT NULL,
    CONSTRAINT TLZ712A1_PK PRIMARY KEY (ID_PACKAGE_CALENDAR),
    CONSTRAINT CALENDAR FOREIGN KEY (CALENDAR_ID) REFERENCES OA1P.TLZ711A1(ID_CALENDAR) ON DELETE RESTRICT,
    CONSTRAINT "PACKAGE" FOREIGN KEY ("PACKAGE") REFERENCES OA1P.TLZ716A1(NAME) ON DELETE RESTRICT
);
CREATE UNIQUE INDEX ILZ712A0 ON OA1P.TLZ712A1 (ID_PACKAGE_CALENDAR);

【问题讨论】:

两个表都是OA1P.TLZ712A1,每个ID_PACKAGE_CALENDAR(在USING 子句中)都存在于合并表中,因为PC2 只是PC 的一个子集。那么NOT MATCHED 不可能发生 @nfgl 有道理。我的想法是,如果找不到记录,NOT MATCHED 将触发。你知道一种方法来完成我想做的事情吗? 请将您的表格描述添加到您的问题中(作为文本),同时添加minimal reproducible example。 @nfgl 我没有设法将 DDL 加载到 SQLFiddle 中,但我用更多信息更新了问题。 所以您的目标是将ACT_DATE 设置为 31.12.2021,如果找到具有PACKAGE = M2108 和CALENDAR_ID = 13 的行并且如果没有找到具有这些值的行,则插入它.我说的对吗? 【参考方案1】:

如果您的目标是将 ACT_DATE 设置为 31.12.2021,如果找到 PACKAGE = M2108 和 CALENDAR_ID = 13 的行,如果没有找到具有这些值的行,则插入它,那么这可能就是答案

MERGE INTO OA1P.TLZ712A1 AS PC
USING (
   VALUES ('M2108', 13, date '31.12.2021')
) PC2 ("PACKAGE", CALENDAR_ID, ACT_DATE)
ON (PC."PACKAGE", PC.CALENDAR_ID) = (PC2."PACKAGE", PC2.CALENDAR_ID)
WHEN MATCHED THEN 
    UPDATE SET ACT_DATE = PC2.ACT_DATE
WHEN NOT MATCHED THEN 
    INSERT ("PACKAGE", ACT_DATE, CALENDAR_ID, PREPTA, MIXED) VALUES (PC2."PACKAGE", PC2.ACT_DATE, PC2.CALENDAR_ID, 0, 0)

【讨论】:

以上是关于Upsert(合并)用于更新记录(如果存在),否则插入的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy - 在 postgresql 中执行批量 upsert(如果存在,更新,否则插入)

mysql实现upsert

《MongoDB入门教程》第20篇 文档更新之UPSERT

《MongoDB入门教程》第20篇 文档更新之UPSERT

SQL Server 2005 中的原子 UPSERT

如何在 PostgreSQL 中进行 UPSERT(合并、插入……重复更新)?