是否可以将列作为参数传递给 ORDER BY 子句?
Posted
技术标签:
【中文标题】是否可以将列作为参数传递给 ORDER BY 子句?【英文标题】:Is it possible to pass a column as a parameter to a ODER BY clause? 【发布时间】:2018-01-09 12:03:08 【问题描述】:我想在 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)---------
我的代码中的问题是我忘记将选择强制转换为我的对象。
这样代码就可以工作了。
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
【问题讨论】:
How to generate Dynamic Order by clause in PL/SQL procedure?的可能重复 您好,需要研究动态SQLdocs.oracle.com/cloud/latest/db112/LNPLS/dynamic.htm#LNPLS011 【参考方案1】:在下面的示例中,我向您展示了如何通过仅订购 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.
【讨论】:
感谢@XING,您的回答像魅力一样解决了我的问题。 如果我想要一个对象的表,我只需要先创建 MY_OBJECT,然后将表的类型(在您的示例中为 VAR_RET)设置为 MY_OBJECT。对吗? @Odilon 完全正确,但您根本无法声明对象变量。创建对象后,您将创建对象的类型。就像我在我的示例中创建了一种表格编号一样。试试看,如果您遇到任何问题,请告诉我 我更新了@XING 的问题。我遗漏了一些东西,因为我的函数不能处理多个列。 非常感谢!它工作得很好。我忘记将选择强制转换为我的对象。以上是关于是否可以将列作为参数传递给 ORDER BY 子句?的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 2008 中使用设计器将逗号分隔列表作为参数传递给 db2 查询的 IN 子句
是否可以将可变数量的参数传递给redshift中的存储过程?
将对象作为参数传递给 router.push (vue-router@4.05)