在Oracle SQL中声明和设置不同数据类型的变量

时间:2013-06-29 03:22:51

标签: sql oracle

我目前正在编写一个SQL查询,它首先使用WITH运算符和SELECT语句创建大量临时表,然后在最后加入所有临时语句。

我创建临时表的所有SELECT语句都依赖于某些过滤器...所以我的查询看起来像是谎言

  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.... 

我想对'sell_date'(日期或字符串)的范围和'product_category'的不同值(整数值)运行此查询。

目前,我正在手动替换这些,但我想知道我是否可以声明用变量替换这些硬编码值,我在查询的顶部设置。

我知道之前可能会问过这个问题 - 但我很困惑,因为有多种解决方案取决于您使用的SQL的确切版本以及您声明的变量类型。

在这种情况下,我正在寻找一种适用于Oracle SQL的解决方案,我可以在其中指定类型变量。

4 个答案:

答案 0 :(得分:3)

这取决于您运行查询的方式。

如果您使用的是SQL * Plus或TOAD等交互式客户端,则应使用替换变量:

  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
      ),

每次运行查询时,系统都会提示您为这些变量提供值。如果要在多个位置使用相同的值,则使用双&符号&& product_category声明所有出现的变量 - 然后只提示您输入一次。 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
      ),

答案 1 :(得分: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 :(得分: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  )
  ...

...或者直接使用连接,而不是使用子查询。

答案 3 :(得分:0)

转到Anonymous PL / sql Block并使用for循环,您可以遍历所有不同的值。

以下是pl / sql块的结构:

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

此外,您可以使用参数化光标来传递您的值。