我正在尝试运行一堆SQL来检查表中是否存在复合主键值。如果存在,则更新表,否则插入新值。我认为合并声明是这样做的方式。但是我编写的合并在运行时会合并0行。我希望在以下示例中出现NOT MATCHED条件,但事实并非如此。这是测试它的脚本和我正在尝试的MERGE:
CREATE TABLE curformat (storeent_id INTEGER,
setccurr VARCHAR2(3),
roundingmultiple INTEGER,
numbrusg_id INTEGER,
roundingmethod VARCHAR2(1),
decimalplaces INTEGER,
MINAPPROVEAMOUNT NUMBER,
optcounter INTEGER);
INSERT INTO curformat VALUES(-1, 'USD', 1, -1, 'R', 2, NULL, NULL);
----------------------------------------------------------------------
MERGE INTO curformat cf
USING (SELECT *
FROM curformat
WHERE storeent_id = 10201
AND setccurr = 'USD'
AND numbrusg_id = -1
) current_curformat
ON (cf.storeent_id = current_curformat.storeent_id
AND cf.setccurr = current_curformat.setccurr
AND cf.numbrusg_id = current_curformat.numbrusg_id
)
WHEN MATCHED THEN UPDATE
SET roundingmultiple = 1,
roundingmethod = 'R',
decimalplaces = 2,
minapproveamount = NULL
WHEN NOT MATCHED THEN INSERT (storeent_id, setccurr, roundingmultiple, numbrusg_id, roundingmethod, decimalplaces, minapproveamount)
VALUES (10201, 'USD', 1, -1, 'R', 2, NULL
);
在这种情况下,由于
的组合WHERE storeent_id = 10201
AND setccurr = 'USD'
AND numbrusg_id = -1
不是真的,我原本以为什么时候不匹配会被运行。 任何人都可以帮助我理解我在这里不理解的东西吗?我想我错误地使用了MERGE语句?
答案 0 :(得分:3)
sstan已经解释了为什么你的MERGE版本不起作用。当您想要更新/插入curformat
时,您不会从该表中提取行。你有"新"您想要插入表中或想要用于更新的行。
所以 - 实际上很容易修复你的MERGE语句。密切关注" delta"虽然(在USING子句中使用current_format
)。在这种情况下,它是一个由"稀薄空气" (在Oracle中表示"从dual
表")创建。
MERGE INTO curformat cf
USING (SELECT 10201 as storeent_id,
'USD' as setccurr,
-1 as numbrusg_id
FROM dual
) current_curformat
ON (cf.storeent_id = current_curformat.storeent_id
AND cf.setccurr = current_curformat.setccurr
AND cf.numbrusg_id = current_curformat.numbrusg_id
)
WHEN MATCHED THEN UPDATE
SET roundingmultiple = 1,
roundingmethod = 'R',
decimalplaces = 2,
minapproveamount = NULL
WHEN NOT MATCHED THEN INSERT (storeent_id, setccurr, roundingmultiple, numbrusg_id,
roundingmethod, decimalplaces, minapproveamount)
VALUES (10201, 'USD', 1, -1, 'R', 2, NULL
);
这将完全符合您的要求。
但是,这里我们硬编码了没有匹配时要插入的值。这是一个非常糟糕的做法。执行此操作的正确方法是(仅显示最后两行,这是唯一更改的行):
VALUES (current_format.storeent_id, current_format.setccurr,
1, current_format.numbrusg_id, 'R', 2, NULL
);
答案 1 :(得分:1)
看起来你正在向后看。如果我们采用基本的merge
语法:
merge into <target> using <source> ...
...我们的想法是,您有一组定义为source
的行,这些行可能与target
中的某些行匹配,也可能不匹配,并为您定义了如何使用的逻辑将source
合并到target
。但是,为了使merge
语句完全执行任何工作,source
不能为空。
在您的情况下,source
定义为:
SELECT *
FROM curformat
WHERE storeent_id = 10201
AND setccurr = 'USD'
AND numbrusg_id = -1
...不返回任何行,因此无需执行任何操作。 target
可以为空,但如果source
为空,则无法合并到target
。