2016-01-28 87 views
2

讓我們想象一下我有這樣一個查詢如下:元編程的Oracle SQL SELECT語句

SELECT 
    CASE WHEN ONE = 1 THEN 1 ELSE 0 END, 
    CASE WHEN JUST_ONE = 1 THEN 1 ELSE 0 END, 
    CASE WHEN ANOTHER_ONE = 1 THEN 1 ELSE 0 END, 

    CASE WHEN TWO = 1 THEN 1 ELSE 0 END, 
    CASE WHEN JUST_TWO = 1 THEN 1 ELSE 0 END, 
    CASE WHEN ANOTHER_TWO = 1 THEN 1 ELSE 0 END 

    -- 20 more things like that where changes only columns name 
FROM 
    SOME_TABLE; 

正如你可以看到,這兩個羣體之間的唯一區別是,在第一個我使用有列「ONE 「而在第二的是擁有那些‘二’和我有大約30組這樣在我的實際查詢,所以我不知道是否有一種方法可以縮短它以某種方式?

+3

不是普通的SQL,但是您可以嘗試動態生成此查詢 –

+0

我可以使用PL/SQL來實現嗎?我沒有訪問任何編程語言。 – JustMichael

+0

PL/SQL = **過程語言** /結構化查詢語言 – stee1rat

回答

2

因爲它們是不同的列,你必須明確地分別在SELECT列表中提及他們。你不能在純SQL做動態。

我會建議,使用良好的文本編輯器,編寫整個SQL幾乎不需要一兩分鐘。

你可以使用DECODE這將有一些不太語法而不是CASE表達這是冗長。

例如,

DECODE(ONE, 1, 1, 0) AS col1, 
    DECODE(JUST_ONE, 1, 1, 0) AS col2, 
    DECODE(ANOTHER_ONE, 1, 1, 0) AS col3, 
    DECODE(TWO, 1, 1, 0) AS col4, 
    DECODE(JUST_TWO, 1, 1, 0) AS col5, 
    DECODE(ANOTHER_TWO, 1, 1, 0) as col6 

我建議堅持SQL,而不是使用PL/SQL。他們不一樣,他們是不同的引擎。 PL --> Procedural Language

但如果你堅持,那麼你可以通過在所有列使用遊標循環循環[DBA | ALL | USER] _TAB_COLS。你可以使用一個SYS_REFCURSOR看到的數據。首先,你必須建立動態SQL

+0

這個答案可能是最好的辦法。但是可以使用一些技巧在單個SQL語句中運行此查詢。我的答案有一個例子,儘管這種情況有點過於複雜。 –

0

的生成方法(在SQL限制與手冊冊後處理)可以

with src as (
select 'ONE' col_name from dual union all 
select 'TWO' col_name from dual 
) 
select 
'CASE WHEN '||col_name||' = 1 THEN 1 ELSE 0 END,'||chr(10)|| 
'CASE WHEN JUST_'||col_name||' = 1 THEN 1 ELSE 0 END,'||chr(10)|| 
'CASE WHEN ANOTHER_'||col_name||' = 1 THEN 1 ELSE 0 END,'||chr(10) 
from src; 

CASE WHEN ONE = 1 THEN 1 ELSE 0 END, 
CASE WHEN JUST_ONE = 1 THEN 1 ELSE 0 END, 
CASE WHEN ANOTHER_ONE = 1 THEN 1 ELSE 0 END, 

CASE WHEN TWO = 1 THEN 1 ELSE 0 END, 
CASE WHEN JUST_TWO = 1 THEN 1 ELSE 0 END, 
CASE WHEN ANOTHER_TWO = 1 THEN 1 ELSE 0 END, 

請注意,您提供您的列名的列表,並獲得擴展的語法。 通常您需要刪除最後一個分隔符,並添加包裹SELECT框架。

2

下面是動態創建的查詢的一個例子。你可以把它放在例如遊標變量,如果你想創建更多的查詢。

select 'SELECT ' || listagg('CASE WHEN '||column_name||' = 1 THEN 1 ELSE 0 END ' || column_name,',') within group(order by column_name) || ' FROM YOUR_TABLE_NAME' 
from cols 
where data_type in ('NUMBER') 
and table_name = 'YOUR_TABLE_NAME'; 

您可以使用COLS視圖來獲取所有列名和數據類型的所有表。

1

的Oracle SQL元編程通過Oracle數據墨盒與任何類型的結合是可能的。

即使使用現有的包元編程,構建查詢內的查詢是複雜的,應儘量避免。其他答案通常更好,即使它們可能需要額外的步驟並且不是「純」的SQL。

如果你真的需要在單個SQL語句中做所有事情,請試試我的open source project, Method4。安裝後,創建一個示例模式:

create table some_table(
    one number, just_one number, another_one number, 
    two number, just_two number, another_two number); 

insert into some_table values(1,1,1,2,2,2); 

運行該查詢建立了基於數據字典中的實際SELECT語句:

select * from table(method4.dynamic_query(
    q'[ 
     --Find columns that match pattern and aggregate into SELECT list. 
     select 
      'SELECT'||chr(10)|| 
      rtrim(listagg(' CASE WHEN '||column_name||' = 1 THEN 1 ELSE 0 END '||column_name||',', chr(10)) 
       within group (order by order_by1, order_by2), ',')||chr(10)|| 
      'FROM some_table' sql_statement 
     from user_tab_columns 
     join 
     (
      --Column names that might match the pattern [null|JUST_|ANOTHER]SPELLED_NUMBER. 
      select prefix||spelled_number possible_column_names 
       ,order_by1, order_by2 
      from 
      (
       --Numbers 1-10. 
       select upper(to_char(to_date(level, 'j'), 'jsp')) spelled_number 
        ,level order_by1 
       from dual 
       --Increase this number up to the maximum possible number. 
       connect by level <= 10 
      ) 
      cross join 
      (
       --Possible prefixes. 
       select null prefix, 1 order_by2 from dual union all 
       select 'JUST_' prefix, 2 order_by2 from dual union all 
       select 'ANOTHER_' prefix, 3 order_by2 from dual 
      ) 
     ) column_names 
      on user_tab_columns.column_name = column_names.possible_column_names 
     where table_name = 'SOME_TABLE' 
    ]' 
)); 

同樣的查詢將返回基於表的不同列:

 ONE JUST_ONE ANOTHER_ONE  TWO JUST_TWO ANOTHER_TWO 
---------- ---------- ----------- ---------- ---------- ----------- 
     1   1   1   0   0   0 

這是一些嚴重的複雜編碼來避免輸入幾行。當他第一次聽說硬編碼總是很糟糕時,這是一種經理人夢寐以求的解決方案。

這實際上回答了有關元編程Oracle SQL SELECT語句的問題。有一些罕見的情況下,這種方法是挽救生命。但99.9%的時間以簡單的方式做事情更好,即使它自動化程度稍低。

+0

+1雖然複雜,但回答了有關元編程的問題。我認爲可以使用XML解決方案將其最小化。感謝分享這個https://github.com/jonheller1/method4 –