2008-09-25 76 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 = ? 
相關問題