2008-09-25 80 views
12

我有一些代码值表包含一个代码和一个Long ID的描述。Oracle插入通过从多个表中选择,其中一个表可能没有一行

我现在要创建引用了一些代码的帐户类型的条目,所以我有这样的事情:

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和收件人表中检索相应的值被找到他们各自的代码。不幸的是,recipient_code是可空的,因此?替代值可能为空。当然,隐式联接不会返回一行,所以行不会插入到我的表中。

我试过使用NVL吗?和r.recipient_id。

我试过在r.recipient_code =上强制外连接?通过添加(+),但它不是明确的连接,所以Oracle仍然没有添加另一行。

任何人都知道这样做的方式?

我明显可以修改语句,以便从外部查找recipient_id,并且有一个?而不是r.recipient_id,并且不要从收件人表中选择,但我宁愿在1个SQL语句中执行所有这些操作。

回答

22

在这种情况下,Outter连接“按预期”无法正常工作,因为您明确告诉Oracle,只有在该表上的条件匹配时才需要数据。在这种情况下,outter连接变得毫无用处。

一个变通

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, 
+0

会不会这有一个问题是,在tax_status或收件人中有多个条目,以及NULL收件人会发生什么情况ient_code? – 2008-09-25 04:55:49

+0

刚刚尝试过,并且account_type_standard上的recipient_id列的null收件人代码的结果为null。 不知道多个条目,但在我的情况下,表具有唯一的代码,所以我没事。 – Mikezx6r 2008-09-25 12:39:03

+0

根据托尼安德鲁斯,不需要从DUAL中选择序列值。可以只有account_type_standard_seq.nextval。 – Mikezx6r 2008-09-26 12:22:23

3

如果ts.tax_status_code是主或备用键或不是,它是不是在这个问题我清楚。与recipient_code一样的东西。这将是有用的知道。

您可以使用OR来处理绑定变量为空的可能性,如下所示。你会将同样的东西绑定到前两个绑定变量。

如果您关心性能,最好检查您打算绑定的值是否为空,然后发出不同的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)) 
+0

这个查询有没有可能会很慢? – 2008-09-25 17:51:15

3

尝试:

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 = ? 
7

一个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 = ?) 
) 
-2
insert into received_messages(id, content, status) 
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), ''); 
1
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 = ? 
相关问题