【问题标题】:How to write PL/SQL function which returns the result of a select statement having as pararmeters the function's parameters?如何编写 PL/SQL 函数,该函数返回以函数参数为参数的 select 语句的结果?
【发布时间】:2021-08-19 00:32:42
【问题描述】:

我尝试编写一个 PL/SQL 函数,其参数为表名和列名,它以表的形式返回查询结果。 这是我尝试过的:

CREATE TYPE TABLE_RES_OBJ AS OBJECT (
    employee_id number(30) ,
    person_id number(30),
    joined_year number(4), 
    salary number(20,2),
    qualification varchar2(45),
    department varchar2(45)
);
 /
create  TYPE table_ret as TABLE OF  table_res_obj;
 /
create or replace function select_custom(p_tablename varchar2, p_colname varchar2 ) return table_ret
is
    ret table_ret;
    query_txt varchar2(100) := 'SELECT :a from :b';
begin
    execute immediate query_txt bulk collect into ret using  p_colname, p_tablename;
        return ret;
end select_custom;

如您所见,这并不像想要的那样通用,但仍然无法正常工作,它说该表不存在,即使我尝试使用现有表运行它也是如此。

【问题讨论】:

  • 如果表和列是基于参数的,你怎么知道结果有总是TABLE_RES_OBJ的结构?
  • (与直接使用视图或表格相比,您认为有什么优势?)

标签: oracle plsql binding dynamic-sql


【解决方案1】:

没错,它不会那样工作。您必须将表名和列名连接到 select 语句中。对于(简单)示例:

SQL> create or replace type table_res_obj as object
  2    (ename varchar2(20));
  3  /

Type created.

SQL> create or replace type table_ret as table of table_res_obj;
  2  /

Type created.

SQL> create or replace function select_custom
  2    (p_tablename varchar2, p_colname varchar2 )
  3  return table_ret
  4  is
  5    ret table_ret;
  6    query_txt varchar2(100);
  7  begin
  8    query_txt := 'select table_res_obj(' || dbms_assert.simple_sql_name(p_colname) ||') from ' ||
  9                  dbms_assert.sql_object_name(p_tablename);
 10    execute immediate query_txt bulk collect into ret;
 11    return ret;
 12  end select_custom;
 13  /

Function created.

有效吗?

SQL> select select_custom('dept', 'deptno') from dual;

SELECT_CUSTOM('DEPT','DEPTNO')(ENAME)
--------------------------------------------------------------------------------
TABLE_RET(TABLE_RES_OBJ('10'), TABLE_RES_OBJ('20'), TABLE_RES_OBJ('30'), TABLE_R
ES_OBJ('40'))


SQL>

【讨论】:

  • 非常感谢!我不知道我必须在这里使用 dbms_assert !也弄错了类型,如果我只查询它,它必须只包含一个元素。现在效果很好!
  • dbms_assert 是为了防止 SQL 注入。你不必使用它,但如果你这样做很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2023-02-01
  • 1970-01-01
相关资源
最近更新 更多