为啥 BULK COLLECT 在 Oracle Package PROC 中给出错误的绑定变量编译错误?

Posted

技术标签:

【中文标题】为啥 BULK COLLECT 在 Oracle Package PROC 中给出错误的绑定变量编译错误?【英文标题】:Why does BULK COLLECT give a bad bind variable compile error in Oracle Package PROC?为什么 BULK COLLECT 在 Oracle Package PROC 中给出错误的绑定变量编译错误? 【发布时间】:2016-01-07 20:41:46 【问题描述】:

我正在尝试使用 3 个字符串来表示一组姓氏、名字和中间名。

传入的参数最终看起来像这样:

lastNames IN VARCHAR2 := NULL
'Smith/Brown/Green'
firstNames IN VARCHAR2 := NULL,
'Joseph/Dan/Sam'
miNames IN VARCHAR2 := NULL,
'c.//J.'

目标是为动态 SQL 构建一个过滤器,如下所示:

v_namesFilter VARCHAR(32767 BYTE);

v_namesFilter := ' AND (last_name = ''Smith'' AND middle_name = ''C'' AND first_name = ''Joseph'') OR (last_name = ''Brown'' AND first_name = ''Dan'') OR (last_name = ''Green'' AND middle_name = ''J.'' AND first_name = ''Sam'')

到目前为止,我有一个这样的传入参数:

lastNames IN VARCHAR2 := NULL,

然后

IS(

我有:

v_last_names_tab     LAST_NAMES_TAB;

LAST_NAMES_TAB 的定义如下:

create or replace TYPE "LAST_NAMES_TAB" AS TABLE OF LAST_NAMES;

LAST_NAMES 的定义如下:

create or replaceTYPE "LAST_NAMES" AS OBJECT(
  lastName VARCHAR2(32767)
);

在我开始之后,我有:

-- split last names into table
SELECT LAST_NAMES( lastName )
BULK COLLECT INTO :v_last_names_tab
FROM   (
  SELECT trim( regexp_substr(lastNames, '[^/]+', 1, LEVEL) )AS lastName
  FROM   DUAL
  CONNECT BY instr(lastNames, '/', 1, LEVEL - 1) > 0
);

我认为这会填满 TYPE LAST_NAMES_TAB 的名为 v_last_names_tab 的表,如下所示:

lastName
--------
Smith
Brown
Green

但我在尝试编译时收到“Bad Bind variable”:v_last_names_tab”错误消息。

我怎样才能像这样格式化我的传入数据,以便我可以滚动它。

【问题讨论】:

在 PL/SQL 上下文中,您不需要使用冒号 (":") 来指示绑定变量。 【参考方案1】:

您不需要所有额外的类型和对象,并且可以在 PL/SQL 中完成所有操作:

CREATE OR REPLACE FUNCTION split_String(
  i_str    IN  VARCHAR2,
  i_delim  IN  VARCHAR2 DEFAULT ','
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC
AS
  p_result       SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
  p_start        NUMBER(5) := 1;
  p_end          NUMBER(5);
  c_len CONSTANT NUMBER(5) := LENGTH( i_str );
  c_ld  CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
  IF c_len > 0 THEN
    p_end := INSTR( i_str, i_delim, p_start );
    WHILE p_end > 0 LOOP
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
      p_start := p_end + c_ld;
      p_end := INSTR( i_str, i_delim, p_start );
    END LOOP;
    IF p_start <= c_len + 1 THEN
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
    END IF;
  END IF;
  RETURN p_result;
END;
/

CREATE OR REPLACE PROCEDURE get_Names_Filter(
  i_lastNames  IN VARCHAR2,
  i_firstNames IN VARCHAR2,
  i_miNames    IN VARCHAR2,
  o_filter   OUT VARCHAR2
)
AS
  p_ln SYS.ODCIVARCHAR2LIST := split_String( i_lastNames, '/' );
  p_fn SYS.ODCIVARCHAR2LIST := split_String( i_firstNames, '/' );
  p_mn SYS.ODCIVARCHAR2LIST := split_String( i_miNames, '/' );
BEGIN
  FOR i IN 1 .. p_ln.COUNT LOOP
    o_filter := o_filter
                || ' AND ( last_name ' || CASE WHEN p_ln(i) IS NULL THEN 'IS NULL' ELSE '= ''' || p_ln(i) || '''' END
                || ' AND middle_name ' || CASE WHEN p_mn(i) IS NULL THEN 'IS NULL' ELSE '= ''' || p_mn(i) || '''' END
                || ' AND first_name ' || CASE WHEN p_fn(i) IS NULL THEN 'IS NULL' ELSE '= ''' || p_fn(i) || '''' END
                || ')';
  END LOOP;
END;
/

【讨论】:

【参考方案2】:

替换

BULK COLLECT INTO :v_last_names_tab

BULK COLLECT INTO v_last_names_tab

: 开头的绑定变量不是正确的 PL/SQL 语法。

【讨论】:

以上是关于为啥 BULK COLLECT 在 Oracle Package PROC 中给出错误的绑定变量编译错误?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle bulk collect into 的几种用法

oracle plsql中同时记录类型、Collection和Bulk collect

重构 Oracle 存储过程以使用 BULK COLLECT

带有 BULK COLLECT 的 Oracle PL/SQL 6504

ORACLE批量绑定FORALL与BULK COLLECT

Oracle Bulk Collect with Limit and For All 未正确处理所有记录