2017-01-30 72 views
0

我想使用我的函數結果,例如'S500,S600,S700,S800'像另一種語言的子查詢:轉換字符串連接','在oracle中用於子查詢SQL

where dept_no in (my result of function) 

所以我想我的字符串轉換結果是這樣('S500','S600','S700','S800')

我試圖用動態SQL做到這一點,但我無法讓它工作。

+0

請[編輯](HTTP ://stackoverflow.com/posts/4193 0234 /編輯)你的問題,並添加一些代碼。你有任何錯誤信息? –

+0

可以使用regexp_substr https://blogs.oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement將字符串分隔成逗號分區 –

+1

簡而言之:你不能。但是,爲什麼你不改變你的函數返回一個表?然後你可以這樣做:'where dept_no in(從表中選擇dept_no(your_function())' –

回答

0

希望在snipet下足以滿足您的要求。

Approach 1 -> More effective 

--Create a table type of VARCHAR 

CREATE OR REPLACE type string_table 
IS 
    TABLE OF VARCHAR2(100); 

--Function to return tabl type 

CREATE OR REPLACE 
FUNCTION string_manipulate 
    RETURN string_table 
AS 
    str_tab string_table; 
BEGIN 
    SELECT 's00'||level bulk collect INTO str_tab FROM dual CONNECT BY level < 10; 
    RETURN str_tab; 
end; 

--Use function in the query 

SELECT distinct 1 
FROM 
    (SELECT 's001' dn FROM dual 
    UNION ALL 
    SELECT 's002' dn FROM dual 
    UNION ALL 
    SELECT 's003' dn FROM dual 
    UNION ALL 
    SELECT 's004' dn FROM dual 
    UNION ALL 
    SELECT 's005' dn FROM dual 
    UNION ALL 
    SELECT 's006' dn FROM dual 
    UNION ALL 
    SELECT 's007' dn FROM dual 
    UNION ALL 
    SELECT 's008' dn FROM dual 
    UNION ALL 
    SELECT 's009' dn FROM dual 
)a 
WHERE a.dn IN 
    (SELECT * FROM TABLE(string_manipulate) 
); 


--Approach 2 
--Function to get output as mentioned. 

CREATE OR REPLACE 
    FUNCTION string_manipulate 
    RETURN VARCHAR2 
    AS 
    BEGIN 
    RETURN 'S2009,S2020,S2021'; 
    END; 

-- Use function value in a query 

SELECT 1 
FROM dual 
WHERE '''S2009'',''S2020'',''S2021''' = ('''' 
    ||REPLACE(string_manipulate,',',''',''') 
    ||''''); 
+0

這個實現的問題在於,如果數據集較大,最終可能會出現性能問題。優化器將無法確定基數。根據@a_horse_with_no_name的建議,我會對如何生成這個字符串列表感興趣。也許它甚至可能是一個加入。 – BobC

+0

Yeaah我完全同意。我認爲數據量偏低。是的,最好的方法是返回一個表類型的函數。 –

+0

@AvrajitRoy非常感謝您對類型表的想法..我嘗試了許多解決方案,但使用類型表是最好的性能解決方案 –

0

您用逗號標誌需要一個迭代器和文本拆分:

select empno,ename,sal,deptno 
from emp 
where empno in (
select to_number(
rtrim(
substr(emps, 
instr(emps,',',1,iter.pos)+1, 
instr(emps,',',1,iter.pos+1) - 
instr(emps,',',1,iter.pos)),',')) emps 
from (select ','||'7654,7698,7782,7788'||',' emps from t1) csv, 
(select rownum pos from emp) iter 
where iter.pos <= ((length(csv.emps) - 
length(replace(csv.emps,',')))/length(','))-1 
) 

不過還好重寫你的函數返回光標。

0

您可以使用收集:

SELECT * 
    FROM YOUR_TABLE 
WHERE DEPT_NO IN (SELECT * 
        FROM TABLE (SPLIT ('S500,S600,S700,S800')))--splits text with comma, for other chars use split(text, split_char) 

隨着會員的

SELECT * 
    FROM YOUR_TABLE 
WHERE DEPT_NO MEMBER OF SPLIT ('S500,S600,S700,S800')--splits text with comma, for other chars use split(text, split_char) 

分割機能的研究的用法是:

CREATE OR REPLACE TYPE SPLIT_TBL AS TABLE OF VARCHAR2 (32767); 

CREATE OR REPLACE FUNCTION SPLIT (P_LIST VARCHAR2, P_DEL VARCHAR2 := ',') 
    RETURN SPLIT_TBL 
    PIPELINED 
IS 
    L_IDX  PLS_INTEGER; 
    L_LIST VARCHAR2 (32767) := P_LIST; 
BEGIN 
    LOOP 
     L_IDX := INSTR (L_LIST, P_DEL); 

     IF L_IDX > 0 
     THEN 
     PIPE ROW (SUBSTR (L_LIST, 1, L_IDX - 1)); 
     L_LIST := SUBSTR (L_LIST, L_IDX + LENGTH (P_DEL)); 
     ELSE 
     PIPE ROW (L_LIST); 
     EXIT; 
     END IF; 
    END LOOP; 

    RETURN; 
END SPLIT; 
+0

您可以簡化它:'WHERE DEPT_NO MEMBER OF SPLIT('S500,S600,S700,S800') ' – MT0

0
FUNCTION GET_TS_EACH_DAY_DEPARTMENT (P_SER_NO  VARCHAR2, 
            P_TS_DATE DATE 
            ) 
     RETURN STRING_TABLE  
    IS 
    V_DEPT_NO  VARCHAR2 (4000); 
    V_DEPT   VARCHAR2(4000); 
    V_TABLE   STRING_TABLE:=STRING_TABLE(); 
    J NUMBER:=1; 
    BEGIN 
    for i in (select distinct ts_day dayy from WEB_TS_USER_LOCATIONS_V) loop 
    V_TABLE.EXTEND; 
     V_TABLE(J):= WEB_TS_PKG.GET_TS_DAY_DEPARTMENT (P_SER_NO ,P_TS_DATE , i.dayy); 
     J:=J+1; 
    end loop; 
    RETURN V_TABLE; 
    END GET_TS_EACH_DAY_DEPARTMENT;