【问题标题】:Oracle "IN clause" from parameter来自参数的 Oracle“IN 子句”
【发布时间】:2011-10-01 13:08:36
【问题描述】:

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

谢谢

这是 proc(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;

【问题讨论】:

  • 请展示您已经尝试过的内容。
  • 这些是需要更改的预先存在的 oracle procs。如果它可以在没有重大结构变化的情况下完成,那么在这一点上将是可取的。要回答您的问题,不,我没有研究过动态 sql...我也不知道从哪里开始 :)。
  • @CosCallis 我已经尝试了问题中两个链接的变体……主要是想弄清楚table(cast(array as type_array)) 中的那种东西是否可行。我会将过程添加到我的问题中,但此时它又回到了基本过程。
  • @George 动态地,我仍然需要遍历逗号分隔的参数来构建字符串。这可能是可行的,但我在这里太不适合了,以至于它甚至都不好笑。我几乎没有接触过甲骨文。

标签: oracle parameters in-clause


【解决方案1】:

你可以这样使用它:

 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'

【讨论】:

  • 如何为该功能添加指向 oracle 文档的链接?
  • 这个查询的性能很糟糕。最佳答案是速度要快几个数量级:stackoverflow.com/a/6629835/550198
【解决方案2】:

假设声明

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

查询

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

给出与

相同的结果
select * from some_table t where some_column in 
(select column_value from table(cvarchar2('FOO','BAR')))

您可以使用第二个并将 PLSQL 集合传递给表函数。我从 Java 中这样做,...table(?) 完美地工作。与传统的 IN 子句相比,explain plan 似乎还不错。

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

【讨论】:

【解决方案3】:

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

这应该对你有用:

替换:

b.customer_no in (p_Scope);

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

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

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

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

【讨论】:

  • 可能有一种更“优雅”的方式来做到这一点,但这太棒了!工作完美,让我通过了我的驼峰。非常感谢!
  • 如果两个客户号码恰好以相同的数字结尾(例如 12345 和 2345),这会不会有问题?您应该在 both 两边用逗号将 b.customer_no 括起来。
  • @Tim,好点...将为此编辑解决方案。 @Metallicraft 注意到这件事并更新
  • 这仍然是迄今为止最简单的解决方案。其他解决方案包括流水线函数或关联数组 - 更多工作 + 我质疑使用这些东西是否有任何性能优势。值得一提的是这个答案 - 你需要传递一个像“,32,33,”这样的字符串。所以字符串开头和结尾的逗号。
【解决方案4】:

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

   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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多