来自参数的 Oracle“IN 子句”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6629433/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 00:08:05  来源:igfitidea点击:

Oracle "IN clause" from parameter

oracleparametersin-clause

提问by Metallicraft

I'm very unfamiliar with Oracle and am just trying to get this to work. I've looked hereand herebut have no idea how to make it all work. Here's what I need. I need a proc that will accept a comma-delimited string as a parameter that I can use in the "IN clause" of the query and return a cursor result. Is ther a way to do this in one, all-inclusive proc? If not, what are the different steps I need to take? Again, I apologize for my lack of knowledge of Oracle, this is just trying to get something to work real quick.

我对 Oracle 非常不熟悉,我只是想让它工作。我已经看过herehere,但不知道如何让它全部工作。这就是我需要的。我需要一个接受逗号分隔字符串作为参数的过程,我可以在查询的“IN 子句”中使用该参数并返回游标结果。有没有办法在一个包罗万象的过程中做到这一点?如果没有,我需要采取哪些不同的步骤?再次,我为我缺乏 Oracle 知识而道歉,这只是试图让某些东西真正快速地工作。

Thanks

谢谢

Here's the proc (p_Scope would be the comma-delimited input):

这是过程(p_Scope 将是逗号分隔的输入):

create or replace PROCEDURE CU_SELECTION_ID
(
p_Scope IN varchar2,
p_ResultSet OUT SYS_REFCURSOR
)
is
BEGIN
OPEN p_ResultSet FOR
select
b.addr1,
b.addr2,
b.city,
b.country_code,
a.customer_no,
b.des1,
a.entity,
b.main_phone_no,
b.phone_area_code,
b.status,
b.wb_site_url,
b.zip
from
ar_customer a,
ct_addr b
where b.main_loc_flag = 'Y' and
a.customer_no = b.customer_no and
a.entity = b.cust_entity and
b.stk_loc_no = '3' and 
b.customer_no in (p_Scope);
END;

回答by Cos Callis

I believe there is a 'better way', but I'm not sure what it is right now...

我相信有一种“更好的方法”,但我不确定现在是什么......

This should work for you though:

不过,这应该对你有用:

replace:

代替:

b.customer_no in (p_Scope);

with

instr(p_Scope, ','||b.customer_no||',' ) > 0

This will search p_Scope and return a value of > 0 if b.customer_no appears in the list.

如果 b.customer_no 出现在列表中,这将搜索 p_Scope 并返回 > 0 的值。

Make sure that the first andlast character in the list is a comma (',')

确保列表中的第一个和最后一个字符是逗号 (',')

(also, as a new comer to Oracle I found Tech Republicto be a very helpful quick resource.)

(此外,作为 Oracle 的新手,我发现Tech Republic是一个非常有用的快速资源。)

回答by Tomá? Zálusky

Assuming declaration

假设声明

create or replace type cvarchar2 as table of varchar2(4000);

the query

查询

select * from some_table t where some_column in 
('FOO','BAR')

gives same result as

给出相同的结果

select * from some_table t where some_column in 
(select column_value from table(cvarchar2('FOO','BAR')))

You can use second one and pass PLSQL collection into table function. I do it this way from Java where ...table(?)perfectly works. Explain plan seems not too bad in comparison with traditional IN clause.

您可以使用第二个并将 PLSQL 集合传递到表函数中。我是从 Java 以这种方式做到的,在那里我可以...table(?)完美地工作。与传统的 IN 子句相比,解释计划似乎还不错。

Solutions based on text search with delimiters may be performance killer.

基于带分隔符的文本搜索的解决方案可能是性能杀手。

回答by Rajesh D

You can use it this way:

你可以这样使用它:

 SELECT * FROM MATABLE 
 WHERE MT_ID 
    IN (SELECT REGEXP_SUBSTR(MYPARAM,'[^,]+', 1, LEVEL) 
        FROM DUAL 
        CONNECT BY REGEXP_SUBSTR(MYPARAM, '[^,]+', 1, LEVEL) IS NOT NULL))

MYPARAM- '368134,181956'

MYPARAM-'368134,181956'

回答by Cortright

For the record, here's another ugly way to do it.

为了记录,这是另一种丑陋的方法。

   PROCEDURE getreport (
      p_affiliates           IN       varchar2,
      p_StartDate            IN       date,
      p_EndDate              IN       date,
      p_ReturnValue         OUT       sys_refcursor
   ) IS
   BEGIN

        DECLARE
           sql_stmt          VARCHAR2(4000);
        BEGIN

          sql_stmt := 'SELECT
            FIRSTNAME,
            LASTNAME,
            ADDRESSLINE,
            SUITE,
            CITY,
            STATE,
            ZIP
        FROM 
            ORDERHEADER head
            INNER JOIN ORDERDETAIL detail 
                on head.ORDERTRACKINGLOGID = detail.ORDERTRACKINGLOGID
            INNER JOIN ORDERTRACKINGDETAIL trackdetail
                on detail.ORDERDETAILID = trackdetail.ORDERDETAILID 
                    AND head.ORDERHEADERID = trackdetail.ORDERHEADERID
            INNER JOIN AFFILIATE aff
                on trackdetail.AFFILIATEID = aff.AFFILIATEID
        WHERE
            aff.AFFILIATEID IN
            (
                select 
                    AFFILIATEID
                from 
                    AFFILIATE
                where
                    AFFILIATEID IN (' || p_affiliates || ')
            )
            AND
            head.CALENDAR_DATE >= TO_DATE( :p_StartDate )
            AND
            head.CALENDAR_DATE <= TO_DATE( :p_EndDate )    
        ORDER BY AFFILIATEID,
                AFFILIATENAME    
    ';

        OPEN p_ReturnValue for sql_stmt USING p_StartDate, p_EndDate;

        END;

    END getreport;