2014-05-16 40 views
0

問我的問題的最簡單方法是使用假設情景。從多個查詢中的一個表或另一個表中選擇數據PL/SQL

可以說我們有3張桌子。 Singapore_Prices,Produce_val和Bosses_unreasonable_demands。

所以價格是一個非常簡單的表格。包含名稱的項目列和包含數字的Price列。

Produce_Val也是簡單的2列表。類型列包含產品是什麼類型(水果或蔬菜),然後是名稱列(番茄,菠蘿等)

Bosses_unreasonable_demands只包含一列Fruit,其中可以包含一些水果的名稱。

好嗎?好。所以,我的老闆要我寫一個查詢,在他的不合理的需求表中返回每個水果的價格。夠簡單。但是,如果他的表中沒有任何條目,他只希望我輸出存在於produce_val中的所有水果的價格。

現在,假設我不知道是誰設計這個愚蠢的假設系統的DBA生活(因此不能讓他解決這個問題),我們的查詢應該是這樣的:

if <Logic to determine if Bosses demands are empty> 
Then 
select Item, Price 
from Singapore_Prices 
where Item in (select Fruit from Bosses_Unreasonable_demands) 
Else 
select Item, Price 
from Singapore_Prices 
where Item in (select Name from Produce_val where type = 'Fruit') 
end if; 

(那麼,我們將選擇這些變量,然後輸出變量,可能與批量收集shenanigans,但這並不重要)

哪個工作。即使我們將其擴展到除新加坡以外的其他2000家商店,它也是完全有效的,並且速度不會太慢。 (好吧,不要比任何其他觸及2000個表的東西慢),但是,我仍然在做兩個不同的select語句,它們幾乎完全相同。每次我的手指碰到ctrl-V,我的Comp Sci老師都會在他們的墳墓中滾動。我可以減少一半的代碼,只做一個選擇語句。我知道我可以。

我只是沒有地球的想法如何。我不能使用遊標作爲聲明,我不能使用嵌套表或變量,我不能使用巧妙製作的字符串,我......我只是......我不知道。我不知道該怎麼做。有沒有辦法?它存在嗎?

還是我必須永遠複製/粘貼?

回答

0

你最好的選擇將是動態的SQL,因爲你不能參數表或列名。

您將擁有一個SQL查詢模板,具有確定要查詢的表和列的邏輯,然後將它們混合在一起並執行。

另一種形式給出,(還是有很多像代碼CTRL-V的)是使用集建築UNION ALL:

select 1st query where boss_condition 
union all 
select 2nd query where not boss_condition 
0

我想你可以使用嵌套表。假定您有一個模式級嵌套表類型FRUIT_NAME_LIST(使用CREATE TYPE定義)。

SELECT fruit 
    BULK COLLECT INTO my_fruit_name_list 
    FROM bosses_unreasonable_demands 
; 

IF my_fruit_name_list.count = 0 THEN 
    SELECT name 
    BULK COLLECT INTO my_fruit_name_list 
    FROM produce_val 
    WHERE type='Fruit' 
    ; 
END IF; 

SELECT item, price 
    FROM singapore_prices 
    WHERE item MEMBER OF my_fruit_name_list 
; 

(或者,如果你喜歡這更好)

+0

這聽起來像我想要的,所以我給了他們一個鏡頭。 您的第一個解決方案提供了一個錯誤「SQL語句中不允許使用本地集合類型」 第二個解決方案是無效數據類型錯誤。 – user3641364

+0

「嵌套表類型」我的意思是在模式級別使用'CREATE TYPE'定義一個,而不是在PL/SQL塊中聲明的一個。這聽起來像你做了後者。我會編輯澄清(我希望)。 –

0

試試這個:

SELECT * 
    FROM (SELECT s.*, 'BOSS' AS FRUIT_SOURCE 
      FROM BOSSES_UNREASONABLE_DEMANDS b 
      INNER JOIN SINGAPORE_FRUIT_LIST s 
      ON s.ITEM = b.FRUIT 
      CROSS JOIN (SELECT COUNT(*) AS BOSS_COUNT 
         FROM BOSSES_UNREASONABLE_DEMANDS)) x 
    UNION ALL 
     (SELECT s.*, 'NORMAL' AS FRUIT_SOURCE 
      FROM PRODUCE_VAL p 
      INNER JOIN SINGAPORE_FRUIT_LIST s 
      ON (s.ITEM = p.NAME AND 
       s.TYPE = 'Fruit') 
      CROSS JOIN (SELECT COUNT(*) AS BOSS_COUNT 
         FROM BOSSES_UNREASONABLE_DEMANDS)) n 
    WHERE (BOSS_COUNT > 0 AND FRUIT_SOURCE = 'BOSS') OR 
     (BOSS_COUNT = 0 AND FRUIT_SOURCE = 'NORMAL') 

分享和享受。

相關問題