0

我有点吃醋了。我有一个接受参数并返回查​​询结果的存储过程。该查询正在使用 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);

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

4

4 回答 4

0

我认为您选择的位置是 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;

注意:我没有测试过这个,但我认为这样你会达到你想要的

于 2012-12-05T19:11:12.517 回答
0

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

看这里 - 返回一个表: SQL 过程可以返回一个表吗?

这是另一个例子:

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;
于 2012-12-06T14:15:25.007 回答
0

我会在不使用字符串操作的情况下做到这一点。从理论上讲,目前 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.
于 2012-12-06T08:43:48.537 回答
0

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

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

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

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

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

于 2012-12-05T19:04:23.863 回答