如何使Oracle函数中的'order by'子句使用表示数字索引的变量?

时间:2011-09-15 15:40:54

标签: oracle

我正在模仿Sqlplus中可用的DESCRIBE tablename,以通过常规sql提供类似的功能。

我有下面列出的对象/函数,它有效 - 除了order_param子句。它基本上被忽略了。我可以通过以下方式调用该函数:

select * from table(describe('my_table',1));

select * from table(describe('my_table',2));

会产生相同的排序。

如果我在函数的sql子句中用order by order_paramorder by 1替换order by 2,它会按预期工作。

除了使用动态sql(或者让函数实际选择2个sql子句)之外,必须有更好的方法让它工作。

CREATE OR REPLACE TYPE table_description as object (
  column_name varchar2(30),
  column_id   number, 
  data_type   varchar2(30),
  nullable    varchar2(1)
);

CREATE OR REPLACE TYPE table_description_type as table of table_description;

CREATE OR REPLACE FUNCTION describe (tname IN VARCHAR2, order_param in NUMBER default 2) RETURN table_description_type AS
-- function to describe a table
-- eg. use via select * from table(describe('table_name'));

  v_ret table_description_type;

BEGIN

 select cast(multiset(
    select column_name, data_type || data_suff "Data Type", nullable from (
      select column_name, column_id, data_type, 
      case when data_type = 'DATE' then '' else '(' ||  
        case when data_type in ('CHAR','VARCHAR2','NCHAR','NVARCHAR') 
        then to_char(char_length) else data_precision || ', ' || data_scale end || ')'
      end data_suff, 
      nullable, data_default, num_nulls, last_analyzed, avg_col_len 
      from all_tab_columns where table_name = upper(tname)
      order by order_param
    )
 ) as table_description_type) into v_ret from dual;

 return v_ret;

END;
/

1 个答案:

答案 0 :(得分:4)

你不能按照你想要的方式做到这一点。为了使order子句将数值解释为列引用,在解析查询时必须存在该数字。由于您将变量绑定在中,因此它始终将您的参数解释为值,而不是列引用。要解决此问题,您需要在逻辑上更改order by子句,以根据值选择列:

order by case order_param 
         when 1 then column_name 
         else data_type || data_suff
         end