我有以下SQL语句,其中order by子句动态传递。 如何将'asc和desc'的命令动态传递给SQL?
SELECT table1.prod_id,table2.prod_name from table1 left outer join table2
ON table1.prod1 = table2.prod_id
ORDER BY CASE WHEN :odb = 1 THEN prod_id END
我想动态地将order by asc or desc
传递给SQL,
我该怎么做?
答案 0 :(得分:7)
您可以通过操纵数字或数据值来执行@TonyAndrews之类的解决方案。对于VARCHAR2
,动态SQL的替代方法可以是两个表达式:
order by
case when :sorting='ASC' then col1 end ASC,
case when :sorting='DESC' then col1 end DESC
当:sorting
的值为'ASC'
时,ORDER BY
的结果会变得如此:
order by
col1 ASC,
NULL DESC
当:sorting
的值为'DESC'
时,ORDER BY
的结果会变得如此:
order by
NULL ASC,
col1 DESC
此方法的一个缺点是优化程序可以跳过SORT操作的那些情况,因为涉及的索引使得数据已经按照需要排序,这在使用这样的CASE方法时不会发生。无论如何,这将要求排序操作。
答案 1 :(得分:3)
如果您要排序的列是数字,那么您可以这样做:
order by case when :dir='ASC' then numcol ELSE -numcol END
对于您可以执行的日期列:
order by case when :dir='ASC' then (datecol - date '1901-01-01')
else (date '4000-12-31' - datecol) end
除了使用动态SQL构建查询(当然适用于任何数据类型)之外,我无法想到VARCHAR2列的合理方法。
答案 2 :(得分:3)
不幸的是,您无法动态执行此操作,因为Oracle会根据这些ASC
和DESC
关键字构建执行计划。
你可以做的是将ORDER BY子句改为:
SELECT * table
ORDER BY :order_param
如果您想按:odb
(:order_param
更大的值将按顺序排序)或ASC
,则将:odb
值传递给1/:odb
您希望按DESC
订购(较大的:odb
值会产生较小的1/:odb
值并显示在结果的顶部。
并且,与往常一样,您可以在存储过程中动态生成查询:
IF ... THEN
EXECUTE IMMEDIATE 'SELECT * table ORDER BY CASE WHEN :odb = 1 THEN 1 END ASC';
ELSE
EXECUTE IMMEDIATE 'SELECT * table ORDER BY CASE WHEN :odb = 1 THEN 1 END DESC';
END IF;
答案 3 :(得分:3)
这适用于所有数据类型:
SELECT *
FROM (SELECT table.*
,ROW_NUMBER() OVER (ORDER BY prod_id) sort_asc
,ROW_NUMBER() OVER (ORDER BY prod_id DESC) sort_desc
FROM table)
ORDER BY CASE WHEN :odb = 1 THEN sort_asc ELSE sort_desc END