通过从多个表中选择进行Oracle插入,其中一个表可能没有行
时间:2020-03-06 14:42:05 来源:igfitidea点击:
我有许多代码值表,其中包含一个代码和一个带有长ID的描述。
现在,我想为引用许多代码的"帐户类型"创建一个条目,因此我有以下内容:
insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) ( select account_type_standard_seq.nextval, ts.tax_status_id, r.recipient_id from tax_status ts, recipient r where ts.tax_status_code = ? and r.recipient_code = ?)
如果找到了各自代码的匹配项,则会从tax_status和收件人表中检索适当的值。不幸的是,receiver_code是可为空的,因此?替换值可以为null。当然,隐式联接不会返回任何行,因此不会将行插入到我的表中。
我尝试在上使用NVL?并在r.recipient_id上。
我试图在r.recipient_code =上强制进行外部联接。通过添加(+),但它不是显式联接,因此Oracle仍未添加另一行。
有人知道这样做的方法吗?
我显然可以修改该语句,以便在外部进行receive_id的查找,并带有??而不是r.recipient_id,并且根本不从收件人表中进行选择,但是我更愿意在1条SQL语句中完成所有这些操作。
解决方案
在这种情况下,外部联接无法"按预期的方式工作",因为我们已明确告知Oracle,仅在该表上的条件匹配时才需要数据。在这种情况下,外部联接将变得无用。
解决方法
INSERT INTO account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) VALUES( (SELECT account_type_standard_seq.nextval FROM DUAL), (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?), (SELECT recipient_id FROM recipient WHERE recipient_code = ?) )
[编辑]
如果期望子选择有多个行,则可以将ROWNUM = 1添加到每个where子句中,或者使用汇总(例如MAX或者MIN)。当然,这可能不是所有情况下的最佳解决方案。
[编辑]每条评论,
(SELECT account_type_standard_seq.nextval FROM DUAL),
可以只是
account_type_standard_seq.nextval,
对于ts.tax_status_code是主键还是备用键,这个问题对我来说还不清楚。与收件人代码相同。知道这一点将很有用。
我们可以使用OR来解决绑定变量为null的可能性,如下所示。我们将把相同的东西绑定到前两个绑定变量。
如果我们担心性能,最好检查要绑定的值是否为null,然后发出不同的SQL语句以避免OR。
insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) ( select account_type_standard_seq.nextval, ts.tax_status_id, r.recipient_id from tax_status ts, recipient r where (ts.tax_status_code = ? OR (ts.tax_status_code IS NULL and ? IS NULL)) and (r.recipient_code = ? OR (r.recipient_code IS NULL and ? IS NULL))
尝试:
insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) select account_type_standard_seq.nextval, ts.tax_status_id, ( select r.recipient_id from recipient r where r.recipient_code = ? ) from tax_status ts where ts.tax_status_code = ?
Oglester解决方案的略微简化版本(该序列不需要从DUAL中进行选择:
INSERT INTO account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) VALUES( account_type_standard_seq.nextval, (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?), (SELECT recipient_id FROM recipient WHERE recipient_code = ?) )
insert into received_messages(id, content, status) values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), '');