是否可以将列作为参数传递给ODER BY子句?

时间:2018-01-09 12:03:08

标签: oracle function plsql parameters

我想在Oracle中使用一个函数。但是我需要相应地使用ORDER BY作为参数传递的内容。

示例:

FUNCTION foo_function(p_date IN DATE, p_column_number IN NUMBER)
RETURN foo_bar
IS
BEGIN
   SELECT * FROM bar WHERE date = p_date ORDER BY p_column_number
   <...other code...>
END;

此块不起作用。 是否可以执行类似的操作将列作为参数传递给ORDER BY子句?

更新----------

@XING显示了一种非常好的方法来解决没有DECODE的问题,就像其他问题的答案一样。

但问题是我错过了什么。 现在我收到此错误:"inconsistent datatypes: expected %s got %s"

-- Creating my object with 2 columns.
CREATE OR REPLACE TYPE MY_OBJECT AS OBJECT(IDOP NUMBER, EMISSION_DATE DATE);

-- Creating the table of MY_OBJECT type.
CREATE OR REPLACE TYPE TB_OBJECT AS TABLE OF MY_OBJECT;

-- Creating my function
CREATE OR REPLACE FUNCTION GET_OBJECT(
   P_INITIAL_DATE IN DATE,
   P_FINAL_DATE IN DATE,
   P_COLUMN_NUMBER   IN   NUMBER)
   RETURN TB_OBJECT
IS
   V_TB       TB_OBJECT;
   V_SQL      VARCHAR2(1000);
BEGIN
   V_SQL :=
      'SELECT IDOP, EMISSION_DATE FROM OP WHERE EMISSION_DATE BETWEEN :p_initial_date AND :p_final_date ORDER BY :p_column_number';

   EXECUTE IMMEDIATE V_SQL
   BULK COLLECT INTO V_TB
             USING P_COLUMN_NUMBER;

   RETURN (V_TB);
END;

-- Calling the function
SELECT * FROM TABLE (GET_OBJECT(TO_DATE('01/06/2017','dd/MM/yyyy'), TO_DATE('09/01/2018', 'dd/MM/yyyy'), 1));

更新(2)---------------------

我的代码中的问题是我忘了将select转换为我的对象。

这样代码就可以了。

V_SQL :=
      'SELECT MY_OBJECT(IDOP, EMISSION_DATE) FROM OP WHERE EMISSION_DATE BETWEEN :p_initial_date AND :p_final_date ORDER BY :p_column_number';

谢谢@XING

1 个答案:

答案 0 :(得分:2)

在下面的示例中,我将通过仅排序1列来向您展示如何在函数中执行此操作。您可以根据需要修改功能;

--Created a type of number to return the ordered result. You can create an object with the column same as used in your select statement.
CREATE OR REPLACE TYPE VAR_RET AS TABLE OF NUMBER;
/

- 功能

CREATE OR REPLACE FUNCTION FOO_FUNCTION (     
     P_COLUMN_NUMBER   IN   NUMBER)
     RETURN VAR_RET
IS
     V_RES                         VAR_RET;
     v_sql                         VARCHAR2(1000);
BEGIN
     V_SQL :=
          'SELECT EMPNO FROM EMP   ORDER BY :p_column_number'; --<-- Create Object with all the columns you are selecting here and then a type of your object to hold result

     EXECUTE IMMEDIATE V_SQL
     BULK COLLECT INTO V_RES
                 USING P_COLUMN_NUMBER;

     RETURN (V_RES);
END;

- 结果:

SQL>  select * from table( FOO_FUNCTION (1));

COLUMN_VALUE
------------
        7369
        7499
        7521
        7566
        7654
        7698
        7782
        7788
        7839
        7844
        7876

编辑:有2个栏目订购

CREATE OR REPLACE TYPE MY_TAB AS OBJECT
(
 V_EMPNM   VARCHAR2(100),
 V_EMPNO   NUMBER
);

CREATE OR REPLACE  TYPE VAR_RET AS TABLE OF MY_TAB;
/



CREATE OR REPLACE FUNCTION FOO_FUNCTION (     
     P_COLUMN_NUMBER   IN   NUMBER)
     RETURN VAR_RET
IS
     V_RES                         VAR_RET;
     v_sql                         VARCHAR2(1000);
BEGIN
     V_SQL := --You need to cast your select statement as per Object
          'SELECT MY_TAB(ENAME,EMPNO) FROM EMP ORDER BY :p_column_number'; --<-- Create Object with all the columns you are selecting here and then a type of your object to hold result

     EXECUTE IMMEDIATE V_SQL
     BULK COLLECT INTO V_RES
                 USING P_COLUMN_NUMBER;

     RETURN (V_RES);
END;

执行: 1)方式1

DECLARE
     VAR                           VAR_RET := VAR_RET ();
BEGIN
     VAR := FOO_FUNCTION (1);

     FOR I IN 1 .. VAR.COUNT
     LOOP
          DBMS_OUTPUT.PUT_LINE (VAR (I).V_EMPNM ||'  ' ||VAR (I).V_EMPNO);
     END LOOP;
END;

SQL> /
SMITH  7369
ALLEN  7499
WARD  7521
JONES  7566
MARTIN  7654
BLAKE  7698
CLARK  7782
SCOTT  7788
KING  7839
TURNER  7844
ADAMS  7876
JAMES  7900
FORD  7902
MILLER  7934

PL/SQL procedure successfully completed.

2)方式2

 select * from table( FOO_FUNCTION (1));

V_EMPNM                                                                                                 V_EMPNO
----------------------------------------------------------------------------------------------------
SMITH                                                                                                      7369
ALLEN                                                                                                      7499
WARD                                                                                                       7521
JONES                                                                                                      7566
MARTIN                                                                                                     7654
BLAKE                                                                                                      7698
CLARK                                                                                                      7782
SCOTT                                                                                                      7788
KING                                                                                                       7839
TURNER                                                                                                     7844
ADAMS                                                                                                      7876

V_EMPNM                                                                                                 V_EMPNO
----------------------------------------------------------------------------------------------------
JAMES                                                                                                      7900
FORD                                                                                                       7902
MILLER                                                                                                     7934

14 rows selected.