SQL动态ASC和DESC

时间:2014-11-19 11:22:41

标签: sql oracle sql-order-by

我有以下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,

我该怎么做?

4 个答案:

答案 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会根据这些ASCDESC关键字构建执行计划。 你可以做的是将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