我编写了以下脚本,以便根据匹配条件插入多行:
Insert
Into RATE_HEADER_NEGOTIATED (RESORT, RATE_CODE, NAME_ID, BEGIN_DATE, END_DATE,
INSERT_USER, INSERT_DATE, UPDATE_USER, UPDATE_DATE, ORDER_BY)
(SELECT 'HRHLC','ST20B',NAME_ID,'01-JAN-2016','12-FEB-2016',
'327','12-FEB-2016','327','12-FEB-2016','1'
from rate_header_negotiated
where resort = 'HRHLC'
and RATE_CODE = 'ST20BL'
and RATE_CODE <> 'ST20B'
and END_DATE >= '01-JAN-16');
我的问题是它给了我重复的密钥错误,因为已经存在包含&#39; ST20B&#39; - 我需要修复脚本的那一部分,这样它只会在不包含ST20B的行上插入行。如果我在运行之前手动删除重复的行,脚本就可以工作。
答案 0 :(得分:1)
如果第一个条件成立,那么第二个也必须如此,所以它是多余的:
and RATE_CODE = 'ST20BL'
and RATE_CODE <> 'ST20B'
您似乎想要排除具有该值的行,因此您需要not exists
子句:
insert into RATE_HEADER_NEGOTIATED (RESORT, RATE_CODE, NAME_ID, BEGIN_DATE,
END_DATE,INSERT_USER, INSERT_DATE, UPDATE_USER, UPDATE_DATE, ORDER_BY)
select 'HRHLC', 'ST20B', NAME_ID, DATE '2016-01-01',
DATE '2016-02-12', 327, DATE '2016-02-12', 327, DATE '2016-02-12', 1
from rate_header_negotiated rhn
where RESORT = 'HRHLC'
and RATE_CODE = 'ST20BL'
and END_DATE >= DATE '2016-01-01'
and not exists (
select null
from rate_header_negotiated
where RESORT = rhn.RESORT
and NAME_ID = rhn.NAME_ID
and RATE_CODE = 'ST20B'
-- any other key columns
);
您也可以进行左连接或不进行连接,但我认为不存在是非常容易理解的。
从Oracle 11gR2开始,您可以use the IGNORE_ROW_ON_DUPKEY_INDEX hint而不是检查密钥的存在。您可能更喜欢,或者可能更愿意明确表示您希望并希望避免现有记录。它也可以记录错误,但似乎你不需要这里。
我还改为使用日期文字,因此您不依赖于隐式转换或会话NLS设置,并删除了数字周围看起来不正确的单引号,假设这些表格列为数字类型 - 从而避免进一步的隐式转换。