如何从一个函数中 return 多个 ID

How to return multiple ID’s from a function

我需要从一个基于输入的函数中 return table 的 ID。

Create or replace function f(v_input nvarchar) 
Return v_table
Is 
  Select id bulk collect into v_table from table1 where user=v_input ;
  Return v_table
End; 

并且此函数将在 sql 查询中调用,例如

Select * from table2 where id in (f(abc)); 

这是概念。

我们如何在 oracle 中以编程方式执行此操作?如何从一个函数 return 多个记录 ID?

你需要:

  • BEGIN关键字在IS和主块的开始之间。
  • ISBEGIN 之间 BULK COLLECT INTO 的变量声明。
  • return 类型不是变量名。
  • a semi-colon 终止 reutrn 语句。
  • NVARCHAR 应该是 NVARCHAR2.
  • USER 是一个保留字,您不应该将它用作列名;如果你这样做,它必须作为带引号的标识符。

像这样:

Create or replace function f(v_input nvarchar2) 
Return t_table
Is
  v_table t_table;
BEGIN
  Select id bulk collect into v_table from table1 where "USER"=v_input ;
  Return v_table;
End; 
/

那么,如果你已经创建了这些:

CREATE TYPE t_table IS TABLE OF INTEGER;

CREATE TABLE table1 (id INTEGER, "USER" NVARCHAR2(20));

INSERT INTO table1 (id, "USER")
SELECT 1, N'user1' FROM DUAL UNION ALL
SELECT 2, N'user1' FROM DUAL UNION ALL
SELECT 2, N'user2' FROM DUAL UNION ALL
SELECT 3, N'user3' FROM DUAL;

CREATE TABLE table2 (id) AS
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 5;

然后:

Select * from table2 where id MEMBER OF f('user1');

Select * from table2 where id IN (SELECT COLUMN_VALUE FROM TABLE(f('user1'))); 

输出:

ID
1
2

db<>fiddle here

在 Oracle 19c 19.7 及更高版本中,您可以使用 SQL_MACRO 概念来实现此目的,即参数化查询。

如您所见,它已合并到主查询中。

create function f_get_ids(p_user in varchar2)
return varchar2
sql_macro(table)
as
begin
  return q'[select id from table1 where user_name = p_user]';
end;
/
select *
from table2
where id in (select id from f_get_ids('User 1'))
ID | DATA_
-: | :----
 1 | 001  
select *
from dbms_xplan.display_cursor(format => 'TYPICAL')
| PLAN_TABLE_OUTPUT                                                             |
| :---------------------------------------------------------------------------- |
| SQL_ID  9ns9x68zjtvhy, child number 0                                         |
| -------------------------------------                                         |
| select * from table2 where id in (select id from f_get_ids('User 1'))         |
|                                                                               |
| Plan hash value: 2946371633                                                   |
|                                                                               |
| ----------------------------------------------------------------------------- |
| | Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     | |
| ----------------------------------------------------------------------------- |
| |   0 | SELECT STATEMENT   |        |       |       |     6 (100)|          | |
| |*  1 |  HASH JOIN SEMI    |        |     1 |    17 |     6   (0)| 00:00:01 | |
| |   2 |   TABLE ACCESS FULL| TABLE2 |     4 |    28 |     3   (0)| 00:00:01 | |
| |*  3 |   TABLE ACCESS FULL| TABLE1 |     1 |    10 |     3   (0)| 00:00:01 | |
| ----------------------------------------------------------------------------- |
|                                                                               |
| Predicate Information (identified by operation id):                           |
| ---------------------------------------------------                           |
|                                                                               |
|    1 - access("ID"="ID")                                                      |
|    3 - filter("USER_NAME"='User 1')                                           |
|                                                                               |

db<>fiddle here