pl/sql 函数 - 为 SELECT ... NOT IN() 动态传递多个 varchar2 值

Posted

技术标签:

【中文标题】pl/sql 函数 - 为 SELECT ... NOT IN() 动态传递多个 varchar2 值【英文标题】:pl/sql function- pass multiple varchar2 values dynamically for SELECT ... NOT IN() 【发布时间】:2014-03-05 05:47:27 【问题描述】:

我有一张表EMP,其定义如下:

EMP_ID         NOT NULL   NUMBER(6)    
EMP_NAME       NOT NULL   VARCHAR2(25) 
EMAIL          NOT NULL   VARCHAR2(25) 
PHONE_NUMBER              VARCHAR2(20) 
HIRE_DATE      NOT NULL   DATE         
JOB_ID         NOT NULL   VARCHAR2(10) 
SALARY                    NUMBER(8,2)

如果我们想计算姓名不在“King”、“Steve”、“John”中的员工,我们只需使用以下查询:

SELECT count(*) FROM emp WHERE emp_name NOT IN('King','Steve','John');


现在这是我想要的:

我想做的是,创建一个PL/SQL Function,它根据动态输入返回计数,就像我们通过:

SELECT count_emp('King,Steve,John') FROM dual;
SELECT count_emp('William,Donald') FROM dual;
SELECT count_emp('Daniel') FROM dual;

需要返回适当的计数,我如何使用PL/SQL FUNCTION 实现此目的


这是我尝试过的,需要指南:

CREATE OR REPLACE FUNCTION count_emp(emp_nm IN varchar) 
RETURN number
IS
  cnt      NUMBER;
BEGIN
  SELECT count(*) INTO cnt FROM emp WHERE emp_name NOT IN(emp_nm);
  RETURN cnt;
END;

它给出了单个名称的结果,但是我如何拆分/格式化多个输入(即emp_nm)以传入NOT IN()

【问题讨论】:

您可以将字符串放入一个变量中拆分它,然后将列表传递到 in 子句中,这样您就可以使用 'King','Steve','John' 而不是 'King,Steve,约翰 您也可以使用动态 SQL。 SO上有很多类似的问题。 即this 和 another one. How to use parameters in a 'where value in...' clause?的可能重复 【参考方案1】:

这样试试,

CREATE OR REPLACE 
FUNCTION count_emp(emp_nm IN VARCHAR) 
RETURN NUMBER
IS
     cnt      NUMBER;
BEGIN
     SELECT count(*) 
     INTO   cnt 
     FROM   emp
     WHERE  ename NOT IN(
          SELECT regexp_substr (emp_nm, '[^,]+', 1, ROWNUM)
          FROM   dual  
          CONNECT BY LEVEL <= LENGTH (regexp_replace (emp_nm, '[^,]+'))  + 1);

     RETURN cnt;
END;

【讨论】:

【参考方案2】:

你可以试试动态sql:

CREATE OR REPLACE FUNCTION count_emp(emp_nm IN varchar) 
RETURN number
IS
  cnt      NUMBER;
BEGIN
  Execute immediate 'SELECT count(*) FROM emp WHERE emp_name NOT IN(' || emp_nm || ')'  returning into cnt;
  RETURN cnt;
END;

【讨论】:

【参考方案3】:

您也可以使用MEMBER OF。这是一个sn-p。希望这会有所帮助!

-- Create a type in SQL    
CREATE OR REPLACE TYPE t_emp_name AS TABLE OF VARCHAR2 (10);

-- use MEMBER OF to use your list as IN parameter    
CREATE OR REPLACE FUNCTION count_emp (emp_nm IN t_emp_name)
   RETURN NUMBER
IS
   cnt   NUMBER;
BEGIN
   SELECT COUNT (*)
     INTO cnt
     FROM emp
    WHERE emp_name NOT MEMBER OF (emp_nm);

   RETURN cnt;
END;

-- Assign values to the list, you can do it dynamically as well. Call the function
DECLARE
   l_emp_name_list   t_emp_name;
   lv_count          NUMBER;
BEGIN
   l_emp_name_list := t_emp_name ('King', 'Steve'); --add more names as needed
   lv_count := count_emp (l_emp_name_list);
END;

【讨论】:

这正是我所需要的。感谢分享! 很高兴看到它有帮助!

以上是关于pl/sql 函数 - 为 SELECT ... NOT IN() 动态传递多个 varchar2 值的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE 中的 PL/SQL、IF-ELSE 或 SELECT DECODE 哪个更好

如何在 PL/SQL 中使用 select 语句为 SQL*Plus 变量赋值?

PL/SQL中SELECT总结

如何在 pl/sql 函数中的变量中存储多行?

PL/SQL - 作为表名的函数参数 - 这怎么可能?

PL/SQL编程—函数