我目前正在编写一个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的解决方案,我可以在其中指定类型变量。
答案 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;
此外,您可以使用参数化光标来传递您的值。