gpt4 book ai didi

sql - Oracle - 不对未修改的值执行更新的 UPSERT

转载 作者:行者123 更新时间:2023-12-01 11:08:25 25 4
gpt4 key购买 nike

我目前正在使用以下更新或插入 Oracle 语句:

BEGIN
UPDATE DSMS
SET SURNAME = :SURNAME
WHERE DSM = :DSM;
IF (SQL%ROWCOUNT = 0) THEN
INSERT INTO DSMS
(DSM, SURNAME)
VALUES
(:DSM, :SURNAME);
END IF;
END;

除了如果数据与提供的参数值相同时更新语句执行虚拟更新之外,这运行良好。我不介意正常情况下的虚拟更新,但是有一个复制/同步系统构建在这个表上,使用表上的触发器来捕获更新的记录并为许多记录频繁执行这个语句仅仅意味着我会在触发器和同步系统。

是否有任何简单的方法来重新制定此代码,使更新语句在没有必要的情况下不会更新记录,而无需使用以下 IF-EXISTS 检查代码,我发现这些代码不够流畅,而且对于此任务可能也不是最有效的?

DECLARE
CNT NUMBER;
BEGIN
SELECT COUNT(1) INTO CNT FROM DSMS WHERE DSM = :DSM;
IF SQL%FOUND THEN
UPDATE DSMS
SET SURNAME = :SURNAME
WHERE DSM = :DSM
AND SURNAME != :SURNAME;
ELSE
INSERT INTO DSMS
(DSM, SURNAME)
VALUES
(:DSM, :SURNAME);
END IF;
END;

我也尝试过使用 MERGE INTO 语句,但是当值未被修改时它不适用于更新(更新不修改任何内容并执行插入,但发生 PK 违规)。

完整的 MERGE INTO 示例:

CREATE TABLE DSMS(
dsm VARCHAR2(10) NOT NULL PRIMARY KEY,
surname VARCHAR2(10) NOT NULL
);
> Table created

-- :DSM = 'xx', :SURNAME = 'xx'
MERGE INTO DSMS D
USING (SELECT :DSM AS DSM,
:SURNAME AS SURNAME
FROM DUAL) V
ON (D.DSM = V.DSM)
WHEN MATCHED THEN
UPDATE
SET SURNAME = V.SURNAME
WHERE D.SURNAME <> V.SURNAME
WHEN NOT MATCHED THEN
INSERT (DSM, SURNAME)
VALUES (V.DSM, V.SURNAME);

> Ok - record inserted

-- :DSM = 'xx', :SURNAME = 'xx'
MERGE INTO DSMS D
USING (SELECT :DSM AS DSM,
:SURNAME AS SURNAME
FROM DUAL) V
ON (D.DSM = V.DSM)
WHEN MATCHED THEN
UPDATE
SET SURNAME = V.SURNAME
WHERE D.SURNAME <> V.SURNAME
WHEN NOT MATCHED THEN
INSERT (DSM, SURNAME)
VALUES (V.DSM, V.SURNAME);

> ORA-00001 - Unique constraint violated (PK violation)

看起来 Oracle 正在使用 UPDATE...IF SQL%ROWCOUNT=0 THEN INSERT... 内部用于 MERGE INTO 子句?第二个 MERGE INTO 语句失败,因为更新不更新任何内容,因此执行 INSERT 导致 PK 违规,因为行已经存在,只是值没有改变。

最佳答案

MERGE
INTO dsms d
USING (
SELECT :DSM AS dsm, :SURNAME AS surname, :FIRSTNAME AS firstname, :VALID AS valud
FROM dual
) v
ON (d.dsm = q.dsm)
WHEN MATCHED THEN
UPDATE
SET SURNAME = v.SURNAME, FIRSTNAME = v.FIRSTNAME, VALID = v.VALID
WHERE d.surname <> v.surname
OR d.firstname <> v.firstname
OR d.valid <> v.valid
WHEN NOT MATCHED THEN
INSERT
INTO (SURNAME, FIRSTNAME, VALID)
VALUES (SURNAME, FIRSTNAME, VALID)

您可能需要添加额外的 NULL 检查您的字段是否接受 NULL 值。

关于sql - Oracle - 不对未修改的值执行更新的 UPSERT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2911628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com