【问题标题】:case, when and then on where clause in stored procedure is not workingcase,when and then on where 存储过程中的子句不起作用
【发布时间】:2013-03-13 09:41:31
【问题描述】:

以下存储过程基于搜索类型(id、编号、名称)和搜索文本('samsung galaxy' 或任何其他等)进行产品搜索。 让我们假设

search_type 是名称search_text 是“三星银河”

基于此条件,我编写了以下存储过程。

create or replace procedure product_search(
    search_type IN varchar2,
    search_text IN varchar2,
    status IN varchar2)
is
cursor c1 is 
    SELECT p.pm_oid , p.item_name  
        FROM prism_item_hierarchy p
        WHERE 
        CASE search_type
             WHEN 'id' THEN p.pm_oid LIKE '%'||search_text||'%'
             WHEN 'name' THEN  Lower(p.item_name ) LIKE '%'||search_text||'%'
             ELSE p.item_number LIKE '%'||search_text
        END;

BEGIN
    open c1;
    -- fetch c1 into 

    close c1;

 END;

但我在 case-when-condition 上收到以下错误:

[Error] ORA-00905 (18: 49): PL/SQL: ORA-00905: missing keyword

能否请您建议我如何解决此问题,即使您建议其他方法来解决此问题,它也会很棒。谢谢

【问题讨论】:

    标签: sql oracle select stored-procedures sqlanywhere


    【解决方案1】:

    这不是在 Oracle 中可以做到的。例如,您可以这样重写您的查询:

    SELECT p.pm_oid , p.item_name  
            FROM prism_item_hierarchy p
            WHERE 
             (search_type='id' AND (p.pm_oid LIKE '%'||search_text||'%')) 
             OR (search_type='name' AND ( Lower(p.item_name ) LIKE '%'||search_text||'%'))
             OR (search_type NOT IN ('id', 'name') AND (p.item_number LIKE '%'||search_text ))
    

    我在这里所做的:我为您使用 CASE-WHEN-THEN 构造所制定的内容制定了一个传统的逻辑表达式。在WHERE 子句中,CASE-WHEN-THEN 不能按照您的方式使用 - 它返回某种值,而您对此没有做任何事情,这就是您得到“缺失关键字”的原因" 错误...

    考虑到这一点,您可以这样做,相应地定义和使用返回值(注意,在这种情况下这是一种扭曲且丑陋的方法!):

    SELECT p.pm_oid , p.item_name  
            FROM prism_item_hierarchy p
            WHERE 
            1 = CASE 
                     WHEN search_type='id' AND (p.pm_oid LIKE '%'||search_text||'%') THEN 1
                     WHEN search_type='name' AND (Lower(p.item_name ) LIKE '%'||search_text||'%') THEN 1
                     WHEN search_type NOT IN ('name','id') AND (p.item_number LIKE '%'||search_text) THEN 1
                     ELSE 0
            END;
    

    但我认为您应该使用IF-THEN-ELSIF-ELSE 构造,并将单个查询分成三个查询:

    IF search_type = 'id' THEN
        SELECT p.pm_oid , p.item_name  
        FROM prism_item_hierarchy p
        WHERE p.pm_oid LIKE '%'||search_text||'%'
    
    ELSIF search_type = 'name' THEN
        SELECT p.pm_oid , p.item_name  
        FROM prism_item_hierarchy p
        WHERE Lower(p.item_name ) LIKE '%'||search_text||'%'
    
    ELSE
        SELECT p.pm_oid , p.item_name  
        FROM prism_item_hierarchy p
        WHERE p.item_number LIKE '%'||search_text
    
    END IF;
    

    这种方法,因为它使用三个不同的查询更加优化:查询优化器将能够为每个查询使用不同的配置文件,因此一般来说,您最终会在每个查询上获得增强的性能。

    【讨论】:

    • 您最后的陈述只是部分正确。如果您在单个存储过程中使用 if then else 语句分成 3 个单独的查询,则 3 个路径中只有一个将存储在查询计划中(第一个被执行)。在重新编译之前,其他 2 个查询将在这个不太理想的查询计划下执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2022-05-05
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    相关资源
    最近更新 更多