将光标与条件

时间:2016-05-27 08:00:45

标签: oracle plsql

我将参数`EBN,BGE'传递给一个过程,然后我将这个参数传递给游标。

create or replace procedure TEXT_MD (AS_IDS  VARCHAR2)
is
CURSOR C_A (AS_ID  VARCHAR2) IS
       SELECT
       name
       FROM S_US
       WHERE US_ID IN (AS_ID);


BEGIN


 FOR A IN C_A (AS_IDS) LOOP

 DBMS_OUTPUT.PUT_LINE('I got here: '||AS_IDS);

end loop;


 END;

enter image description here

但是,在对游标计数进行调试时仍为空

enter image description here

所以我的问题是,为什么游标没有在条件

中返回值

1 个答案:

答案 0 :(得分:2)

您正在传递一个字符串参数,因此它将用作字符串,而不是字符串列表;所以,你的光标将是

SELECT name
FROM S_US
WHERE US_ID IN ('EBN,BGE')

当然,这不会做你需要的。 您可能需要更改过程和传递参数的方式;如果你想保留一个字符串参数,可以采用以下方法:

<强>设置:

SQL> CREATE TABLE S_US
  2  (
  3      US_ID,
  4      NAME
  5  ) AS
  6      SELECT 'EBN', 'EBN name' FROM DUAL
  7      UNION ALL
  8      SELECT 'BGE', 'BGE name' FROM DUAL;

Table created.

<强>过程:

SQL> CREATE OR REPLACE PROCEDURE TEXT_MD_2(AS_IDS VARCHAR2) IS
  2      vSQL varchar2(1000);
  3      c sys_refcursor;
  4      vName varchar2(16);
  5  BEGIN
  6      vSQL := 'SELECT name
  7                FROM S_US
  8               WHERE US_ID IN (' || AS_IDS || ')';
  9      open c for vSQL;
 10      loop
 11          fetch c into vName;
 12          if c%NOTFOUND then
 13              exit;
 14          end if;
 15          DBMS_OUTPUT.PUT_LINE(vName);
 16      END LOOP;
 17  END;
 18  /

Procedure created.

您需要使用已格式化为IN的参数列表的字符串来调用它:

SQL> EXEC TEXT_MD_2('''EBN'',''BGE''');
EBN name
BGE name

PL/SQL procedure successfully completed.

这只是一种可能方式的例子,而不是我这样做的方式。 考虑到这种方法的原因,请考虑Justin Cave所说的内容: &#34;由于SQL注入会带来安全风险,并且由于持续的难以解析而会导致潜在的显着性能损失&#34;。

我相信您应该更好地检查如何将值列表传递给您的过程,而不是使用字符串来表示字符串列表。 以下是使用集合执行相同操作的可能方法:

SQL> CREATE OR REPLACE TYPE tabVarchar2 AS TABLE OF VARCHAR2(16)
  2  /

Type created.

SQL>
SQL> CREATE OR REPLACE PROCEDURE TEXT_MD_3(AS_IDS tabVarchar2) IS
  2      vSQL                                    VARCHAR2(1000);
  3      c                                       SYS_REFCURSOR;
  4      vName                                   VARCHAR2(16);
  5  BEGIN
  6      FOR i IN (SELECT name
  7                  FROM S_US INNER JOIN TABLE(AS_IDS) tab ON (tab.COLUMN_VALUE = US_ID))
  8      LOOP
  9          DBMS_OUTPUT.PUT_LINE(i.name);
 10      END LOOP;
 11  END;
 12  /

Procedure created.

SQL>
SQL> DECLARE
  2      vList                                   tabVarchar2 := NEW tabVarchar2();
  3  BEGIN
  4      vList.EXTEND(2);
  5      vList(1)    := 'BGE';
  6      vList(2)    := 'EBN';
  7      TEXT_MD_3(vList);
  8  END;
  9  /
BGE name
EBN name

PL/SQL procedure successfully completed.

SQL>

同样,您可以在存储过程中以不同方式定义集合,是否已编制索引,等等;这只是其中一种可能的方式,不一定是最好的方式,具体取决于您的环境,需求。