【问题标题】:Passing an array as an argument into an Oracle stored procedure将数组作为参数传递到 Oracle 存储过程
【发布时间】:2012-11-23 16:50:43
【问题描述】:

我有点吃不消了。我有一个接受参数并返回查​​询结果的存储过程。该查询正在使用 IN 语句。

这是 SP 的结构:

CREATE OR REPLACE 
PROCEDURE EXAMPLE_SP
(
   arg VARCHAR2,
   argRS1 OUT cursors.rs
)
AS 
 l_test VARCHAR2(255) := arg;

BEGIN

  OPEN argRS1 FOR
    SELECT * FROM TABLE1
    WHERE LOCATION IN (l_test);

END EXAMPLE_SP;

IN 语句中值的数量可以是可变的。 IN 的选项来自 UI 端的选定表单复选框。

我正在使用 PHP 来检索选定的复选框值。我已经尝试将这些值内爆成逗号分隔的字符串。

我的逻辑是查询将如下所示:

l_test = 'val1,  val2, val3';
SELECT * FROM TABLE1
WHERE LOCATION IN (val1, val2, val3);

但这没有用。我不确定如何进行。提前感谢任何建设性的 cmets 或建议。

【问题讨论】:

    标签: php oracle stored-procedures


    【解决方案1】:

    您可以将此逗号分隔的输入参数添加为 varchar() 并使用以下 where 语句:

    where (','||l_test||',' like '%,'||LOCATION||',%')
    

    例如,如果 l_test='2,3,4,5'LOCATION=3 我们得到:

    where (',2,3,4,5,' like '%,3,%') 
    

    如果 LOCATION 值在此列表中,则为 TRUE。

    【讨论】:

      【解决方案2】:

      我认为您选择的位置是 VARCHAR,因此您需要将列表转换为如下所示

      l_test = '''val1''||','|| ''val2''||','||''val3''';
      

      这样你的最终查询看起来像

      SELECT * FROM TABLE1
      WHERE LOCATION IN ('val1', 'val2', 'val3');
      

      你也可以这样做

      CREATE OR REPLACE 
      PROCEDURE EXAMPLE_SP
      (
        arg VARCHAR2,
        argRS1 OUT cursors.rs
      )
      AS 
       l_test VARCHAR2(255) := arg;
      
       BEGIN
        l_test:=''''||replace(l_test,',',''',''')||'''';
        OPEN argRS1 FOR
          SELECT * FROM TABLE1
           WHERE LOCATION IN (l_test);
      
       END EXAMPLE_SP;
      

      注意:我没有对此进行测试,但我认为这样你会实现你想要的

      【讨论】:

        【解决方案3】:

        我会在不使用字符串操作的情况下做到这一点。从理论上讲,目前 SQL 注入的风险可能很小,因为您使用的是复选框,最好在一开始就实施良好的做法,因此如果有任何变化,您不会将自己置于危险之中。

        第二个好处是您仍然可以使用列上的任何索引,如果您使用 like '%...,您将无法做到这一点。

        为此,您可以利用表格函数和外部对象来填充“in”列表。

        作为示例,我将从 USER_OBJECTS 返回 OBJECT_NAME。

        如果我创建两个表:

        create table tmp_test ( a number );
        create table tmp_test2 ( a number );
        

        还有一个对象来保存表格列表,或者在您的案例中的位置。

        create type t_test_object is table of varchar2(30);
        

        接下来,这是您的程序的等效程序。它是一个返回 SYS_REFCURSOR 的函数。它接受 T_TEST_OBJECT 作为参数,这意味着在传递给函数之前需要先填充它。

        create or replace function select_many (
               Ptest_object in t_test_object
               ) return sys_refcursor is
        
           l_curs sys_refcursor;
        
        begin
        
           open l_curs for
            select object_name
              from user_objects
             where object_name in ( select *
                                      from table(Ptest_object)
                                           );
        
           return l_curs;
        
        end;
        

        最后,这里有一个如何使用此设置的示例。请注意 T_TEST_OBJECT 的实例如何填充多个值。然后这个对象被传递给函数以返回您的光标。最后,要显示值,我会遍历光标。显然,您可能希望使用光标并以不同的方式填充 TYPE。

        SQL> declare
          2
          3     l_nested_table t_test_object := new t_test_object();
          4     l_cursor sys_refcursor;
          5     -- Used for display demonstration only.
          6     l_object_name user_objects.object_name%type;
          7
          8  begin
          9
         10     l_nested_table.extend;
         11     l_nested_table(l_nested_table.last) := 'TMP_TEST';
         12     l_nested_table.extend;
         13     l_nested_table(l_nested_table.last) := 'TMP_TEST2';
         14
         15     l_cursor := select_many(l_nested_table);
         16     
         17     loop -- Display example, not really relevant
         18        fetch l_cursor into l_object_name;
         19        exit when l_cursor%notfound;
         20        dbms_output.put_line(l_object_name);
         21     end loop;
         22
         23  end;
         24  /
        TMP_TEST
        TMP_TEST2
        
        PL/SQL procedure successfully completed.
        

        【讨论】:

          【解决方案4】:

          您可以使用 Oracle 文档中的 Oracle 示例:http://docs.oracle.com/cd/B28359_01/win.111/b28378/basfeat.htm#sthref207

          看这里 - 返回一个表: Can an SQL procedure return a table?

          还有一个例子:

          PACKAGE emp_actions IS
            TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
            TYPE SalTabTyp IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER;
            ...
            PROCEDURE hire_batch (ename_tab IN EnameTabTyp, sal_tab IN SalTabTyp, ...);
            PROCEDURE log_names (ename_tab IN EnameTabTyp);
          END emp_actions;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-24
            • 2023-03-22
            • 1970-01-01
            • 2010-11-07
            相关资源
            最近更新 更多