2016-02-26 54 views
0

我动态构造与名称的user_data在PL/SQL程序字符串,单引号(')和形式WHERE IN条件不通过附加的用户名接受字符串值

'abc123','xyz456','pqr789' 

的逗号(,)但是,当我通过这个字符串凡在SELECT语句

SELECT * FROM table_name WHERE USERNAME IN (user_data) 

它抛出一个NO_DATA_FOUND异常的情况。

另一方面,如果我的字符串只包含一个没有引号的用户,它就能够找到该用户并显示所需的输出。

的数据类型USER_DATA是VARCHAR2。

+3

的可能的复制[参数化子句的SQL](http://stackoverflow.com/questions/337704/parameterize-an-sql-in-clause) –

+0

或这个http://stackoverflow.com/questions/6155146/problem-using-oracle-parameters-in-select-in/6155215#6155215 –

+0

在这两种情况下,你可以打印和发布你的字符串'user_data'的内容,工作不工作? – Aleksej

回答

0

这不是那样的工作。您的表达等于

SELECT * FROM table_name WHERE USERNAME = '''abc123'', ''xyz456'', ''pqr789'''; 

这就是为什么没有结果。

你可以做这样的事情,才达到欲望的效果:

SELECT * FROM table_name WHERE user_data like '%''' || USERNAME || '''%'; 

,但它不会是相同的,但。

3

您可以使用集合做到这一点:

CREATE TYPE VARCHAR2s_Table IS TABLE OF VARCHAR2(100); 
/

然后输入你的数据是这样的:

SELECT * 
FROM table_name 
WHERE user_data MEMBER OF VARCHAR2s_Table('abc123','xyz456','pqr789'); 

或者

您可以创建一个函数来分割数据并生成集合:

CREATE TYPE VARCHAR2_TABLE AS TABLE OF VARCHAR2(4000); 
/

CREATE OR REPLACE FUNCTION split_String(
    i_str IN VARCHAR2, 
    i_delim IN VARCHAR2 DEFAULT ',' 
) RETURN VARCHAR2_TABLE DETERMINISTIC 
AS 
    p_result  VARCHAR2_TABLE := VARCHAR2_TABLE(); 
    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; 
/

然后,你可以这样做:

SELECT * 
FROM table_name 
WHERE user_data MEMBER OF split_String('abc123,xyz456,pqr789', ','); 

或:

SELECT * 
FROM table_name 
WHERE user_data MEMBER OF split_String(TRIM('''' FROM '''abc123'',''xyz456'',''pqr789'''), ''','''); 
0

你可以在你IN第一个动态的字符串是这样的:

SQL> declare 
    2  user_data varchar2(1000); 
    3  vSQL  varchar2(2000); 
    4  type  tabUser is table of varchar2(16); 
    5  outData tabUser; 
    6 begin 
    7  user_data := '''abc'', ''123'', ''zzz'''; 
    8  -- 
    9  vSQL := 'select userName from table_name where username in (' || user_data || ')'; 
10  -- 
11  execute immediate vSQL bulk collect into outData; 
12  -- 
13  dbms_output.put_line('user_data: ' || user_data); 
14  for i in outData.first .. outData.last loop 
15   dbms_output.put_line('User: ' || outData(i)); 
16  end loop; 
17 end; 
18/
user_data: 'abc', '123', 'zzz' 
User: abc 
User: 123 

PL/SQL procedure successfully completed. 

SQL> select * from table_name; 

USERNAME 
---------------- 
abc 
ABC 
123 

在这种情况下,你无论您是否有一个或多个用户名,都必须在字符串中使用带引号的名称。

0

你的SELECT语句

SELECT * FROM table_name WHERE USERNAME IN (user_data)

将被视为

SELECT * FROM table_name WHERE USERNAME = 'abc123','xyz456','pqr789'

这是不正确的。

一个替代方案是

SELECT * FROM table_name WHERE INSTR(user_data, USERNAME) > 0