0

我试图找到一种简单且易于维护的方法来通过可以在SELECT如下语句中引用的函数返回结果集:

SELECT u.UserId, u.UserName, up.ProfileName
FROM GetUser(1) u
INNER JOIN user_profile up ON u.user_id = up.user_id; 

这是我在 Postgres 中的内容:

CREATE OR REPLACE FUNCTION GetUser(
  pUserId INTEGER
)
RETURNS TABLE (UserId INTEGER, UserClass CHAR(2), UserName VARCHAR(100)) AS $$
BEGIN
  RETURN QUERY
  SELECT UserId, UserClass, UserName
  FROM Users 
  WHERE (UserId = pUserId OR pUserId IS NULL)
  ;
END;
$$ LANGUAGE 'plpgsql';

SELECT * FROM GetUser(1);

这是我在 Oracle 中的一个示例:

CREATE OR REPLACE TYPE appuser AS OBJECT (UserName VARCHAR(255)); -- user type
CREATE OR REPLACE TYPE appuser_table AS TABLE OF appuser; -- user table type

CREATE OR REPLACE FUNCTION GetUser (
  pUserId IN VARCHAR2 DEFAULT NULL
) RETURN appuser_table PIPELINED AS
BEGIN
  FOR v_Rec IN (
    SELECT UserName
    FROM Users
    WHERE (UserId = pUserId OR pUserId IS NULL)
  ) 
  LOOP
    PIPE ROW (appuser(v_Rec.UserName));
  END LOOP;

  RETURN;
END;

SELECT * FROM TABLE(GetUser(NULL));

它可以工作,但是很麻烦并且需要多个 DDL。在 Postgres 中,我可以在函数中轻松完成所有这些操作:

RETURNS TABLE (ObjectId INTEGER, ObjectClass CHAR(2), ObjectName VARCHAR(100))

在 Oracle 中有没有更简洁的方法来做到这一点?

相关文章
SELECT in Functions / SPs
DBMS_SQL.return_result
流水线函数

4

2 回答 2

1

在 19.6 之前,具有定义表类型(作为 SQL 类型或在 PL/SQL 包中)的流水线函数是实现此目的的唯一方法。使用此版本后,您可以使用SQL Macros。对于您的特定要求,您可以直接替换,例如:

create or replace function getUser (pUserId  integer) 
return varchar2 sql_macro 
is
begin
  return q'{SELECT UserId, UserClass, UserName
  FROM Users 
  WHERE (UserId = pUserId OR pUserId IS NULL)}';
end getUser;
/

或者,您可以使优化器更容易将查询分成两种可能的形式 - 返回所有内容或仅返回与pUserId值匹配的行:

create or replace function getUser (pUserId  integer) 
return varchar2 sql_macro 
is
begin
  if pUserId is null then 
    return q'{SELECT UserId, UserClass, UserName FROM Users}';
  else 
    return q'{SELECT UserId, UserClass, UserName FROM  Users WHERE UserId = pUserId}';
  end if;
end getUser;
/

在 LiveSQL 上做了一个演示

于 2020-11-22T19:53:55.343 回答
1

基本上,按照你的说法,你只需要创建一个函数——使用Oracle的内置类型。这是一个基于 ScottEMP表格的示例(因为我没有你的):

SQL> select deptno, ename from emp where deptno = 10;

    DEPTNO ENAME
---------- ----------
        10 CLARK
        10 KING
        10 MILLER

功能:

SQL> create or replace function getuser (puserid in number default null)
  2    return sys.odcivarchar2list
  3  is
  4    retval sys.odcivarchar2list;
  5  begin
  6    select ename
  7      bulk collect into retval
  8      from emp
  9      where deptno = puserid or puserid is null;
 10
 11    return retval;
 12  end;
 13  /

Function created.

测试:

SQL> select * From table(getuser(10));

COLUMN_VALUE
----------------------------------------------------------------------------
CLARK
KING
MILLER

SQL>

如果您想获得“更智能”的内容作为列名而不是COLUMN_VALUE,那么您必须创建自己的类型。像这样的东西:

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

Type created.

SQL> create or replace type t_tf_tab is table of t_tf_row;
  2  /

Type created.

SQL> create or replace function getuser (puserid in number default null)
  2    return t_tf_tab
  3  is
  4    retval t_tf_tab;
  5  begin
  6    select t_tf_row(ename)
  7      bulk collect into retval
  8      from emp
  9      where deptno = puserid or puserid is null;
 10    return retval;
 11  end;
 12  /

Function created.

SQL> select * from table(getuser(10));

ENAME
--------------------
CLARK
KING
MILLER

SQL>
于 2020-11-22T14:39:19.203 回答