2013-06-29 41 views
1

我當前正在編寫一個SQL查詢,它首先使用WITH運算符和SELECT語句創建大量臨時表,然後在最後連接所有臨時語句。在Oracle SQL中聲明和設置不同數據類型的變量

所有創建臨時表依賴於特定的過濾器我的SELECT語句的...所以我的查詢看起來是liek

WITH 

    table_1 as (
    SELECT product_id 
      avg(price) 
    FROM daily_sales 
    WHERE product_category = 1 
    AND sell_date BETWEEN TO_DATE('2012/01/07','YYYY/DD/MM') AND TO_DATE('2012/30/09','YYYY/DD/MM') 
    GROUP BY ds.product_id 
), 

    table_2 as (.... 
), 


SELECT FROM table_1 JOIN table_2.... 

我想爲「賣出日」的範圍內運行此查詢(日期,或字符串)和「product_category」(一個整數值)的不同值。

目前,我正在替換這些手動,但我想知道如果我可以聲明用我設置在查詢頂部的變量替換這些硬編碼的值。

我知道這可能以前曾被問過 - 但我很困惑,因爲有多種解決方案依賴於您正在使用的SQL的確切版本以及您聲明的變量類型。

在這種情況下,我正在尋找一種適用於Oracle SQL的解決方案,並且可以指定類型變量。

回答

3

這取決於您如何運行您的查詢。

如果您使用的是交互式客戶端像SQL * Plus或蟾蜍,你應該使用替代變量:

WITH 
     table_1 as (
     SELECT product_id 
       avg(price) 
     FROM daily_sales 
     WHERE product_category = &product_cat 
     AND sell_date BETWEEN TO_DATE('&start_date','YYYY/DD/MM') AND TO_DATE('&end_date','YYYY/DD/MM') 
     GROUP BY ds.product_id 
    ), 

將提示您在每次運行查詢時提供值這些變量。如果您想在多個地方使用相同的值,則使用雙和號聲明變量的所有出現次數 - 產品類別 - 然後您只會提示一次。 SQL * Plus文檔包含其他信息:find out more

如果你要在存儲過程運行查詢然後定義值作爲參數...

procedure process_sales_details 
    (i_product_category in number 
     , i_start_date in date 
     , i_end_date in date) 

...你在查詢中引用(不管你聲明它).. 。

WITH 
     table_1 as (
     SELECT product_id 
       avg(price) 
     FROM daily_sales 
     WHERE product_category = i_product_cat 
     AND sell_date BETWEEN i_start_date AND i_end_date 
     GROUP BY ds.product_id 
    ), 
0

尋找一個匿名PL/sql塊,並使用for循環,你可以遍歷所有不同的值。

以下是PL/SQL塊的結構:

DECLARE 
<constant name> CONSTANT <data type> := <value>; 
<constant name> CONSTANT <data type> DEFAULT <value>; 
BEGIN 
    <valid statement>; 
EXCEPTION 
    <exception handler>; 
END; 

您也可以去一個參數化的光標,你可以通過你的價值觀。

2

繼APC的答案,在SQL * Plus或SQL Developer中,您也可以聲明,你可以在匿名PL/SQL塊賦值,然後引用在你的普通的SQL查詢綁定變量的變量:

variable v_product_cat number; 
variable v_start_date varchar2(10); 
variable v_end_date varchar2(10); 

begin 
    :v_product_cat := 1; 
    :v_start_date := '2012/01/07'; 
    :v_end_date := '2012/30/09'; 
end; 
/

WITH table_1 as (
    SELECT product_id 
      avg(price) 
    from daily_sales 
    where product_category = :v_product_cat 
    AND sell_date BETWEEN TO_DATE(:v_start_date,'YYYY/DD/MM') 
     AND TO_DATE(:v_end_date,'YYYY/DD/MM') 
    group by ds.product_id 
) 
... 

注意:之前的變量名稱表示一個綁定變量,並且字符串沒有用此形式引號括起來。不幸的是,你不能聲明一個date變量,這將使得它更加整潔。

如果你使用替代變量,你可以在開始時define他們,所以你不會提示;在這種情況下,你不需要使用&&符號之一:

define v_product_cat=1 
define v_start_date=2012/01/07 
define v_end_date=2012/30/09 

... 
    where product_category = &v_product_cat 
    and sell_date between to_date('&v_start_date','YYYY/DD/MM') 
     AND TO_DATE('&v_end_date','YYYY/DD/MM') 
... 

...這是覆蓋在鏈接到文件APC。

2

您可以添加一個或多個公用表表達式來封裝這些:

with 
    cte_sell_dates as (
    select date '2012-07-01' from_date, 
      date '2012-09-30' to_date 
    from dual), 
    cte_products as (
    select 1 id from dual union all 
    select 28 id from dual), 
    ... as (
    select ... 
    from ... 
    where sell_date between (select from_date from cte_sell_dates) and 
          (select to_date from cte_sell_dates) and 
      product_id in  (select id  from cte_products ) 
    ... 

...或者使用直接連接,而不是子查詢,當然。