Oracle 具有相同where子句的多个select查询

Oracle 具有相同where子句的多个select查询,oracle,plsql,where-clause,code-design,Oracle,Plsql,Where Clause,Code Design,我有两种类型的select语句,它们具有相同的复杂where子句 一次返回事务详细数据 第二个-返回按不同商户分组的交易数据 语句是单独调用的 我希望简化我的代码,不要在两条语句中重复这个复杂的where子句,而不会降低性能 在动态SQL中这是可能的,但我不想使用动态SQL 有什么建议吗 因此您可以将此语句封装在视图或函数中,例如: create or replace view view_1 as select field_1, field_2, field_3, ... , field_

我有两种类型的select语句,它们具有相同的复杂where子句

一次返回事务详细数据

第二个-返回按不同商户分组的交易数据

语句是单独调用的

我希望简化我的代码,不要在两条语句中重复这个复杂的where子句,而不会降低性能

在动态SQL中这是可能的,但我不想使用动态SQL


有什么建议吗

因此您可以将此语句封装在视图或函数中,例如:

create or replace view view_1 as
   select field_1, field_2, field_3, ... , field_30 
   from my_table 
   where my_where_clause
那么您的第二个查询可能是

 select distinct * from view_1;

您说过您正在使用来自java的这个查询。试试这个

create or replace function  get_cursor(p_type varchar2 default null/* other paramethers*/ ) return sys_refcursor
is 
result_curosr sys_refcursor; 
begin 
open result_curosr for 'select '||p_type||' object_type,status from user_objects' /* where clausele */ ;
return result_curosr;
end;
以及它在java中的用法

Connection con = ...
    CallableStatement  callableStatement = con.prepareCall("declare  c sys_refcursor; begin  ? := get_cursor(?); end ; ");

    callableStatement.registerOutParameter(1,  OracleTypes.CURSOR);

    callableStatement.setString(2, "Distinct"); // for distinct 
or 
    callableStatement.setNull(2, OracleTypes.VARCHAR); // for full results 
    callableStatement.executeUpdate();
    ResultSet rs = (ResultSet) callableStatement.getObject(1);
    while(rs.next()) {
        System.err.println(rs.getString(1));
    }
    rs.close();

        con.close();
其他解决方案。 再添加一个参数,并使用查询中的所有列执行简单的重复数据消除。但我看不出有什么好处

select object_type,status from 
(select object_type,status, row_number() over( partition by object_type,status order by 1) rn from user_objects /* your_where_clusue */
) where rn = case when 'DISTIINCT'/* <- paramete here :isDistinct */  = 'DISTIINCT' then 1 else rn end;
建议:您可以尝试对表达式集进行分组。 它允许您有选择地指定要在GROUPBY子句中创建的组集。在

在您的情况下,可以指定2个集合,一组一组用于1到30的所有字段,另一组用于1、2和8的字段。 链接-


但是,它将在单个结果集中返回两个组的输出,不确定这是否适合您的设计。

您可以使用多行字符串、替代引号和模板使动态SQL更具可读性

declare
    v_select varchar2(32767);
    v_where  varchar2(32767);
    v_code   varchar2(32767) := '
            ##SELECT##
            ##WHERE##
    ';
begin
    --Populate the clauses.
    if ... then
        v_select := 'select field_1, field_2, field_3, ... , field_30 from my_table';
    else
        v_select := 'select distinct field_1, field_2, field_8 from my_table';
    end if;

    if ... then
        v_where :=
        q'[
            where field_1 = 'foo'
                and field_2 = :bind1
                ...
        ]';
    else
        v_where :=
        q'[
            where field_2 = 'bar'
                and field_2 = :bind2
                ...
        ]';
    end if;

    --Fill in the code.
    v_code := replace(v_code, '##SELECT##', v_select);
    v_code := replace(v_code, '##WHERE##', v_where);

    --Print the code to check the formatting.  Remove after testing.
    dbms_output.put_line(v_code);

    --Run it.
    execute immediate v_code using ...;
end;
/

它不是完美的,但它可以防止丑陋的连接。而且它比不惜一切代价避免动态SQL所需的反模式要好得多。在大多数语言中,多态性和反射等特性比动态代码更好。PL/SQL对这些高级功能没有很好的支持,因此通常最好将代码构建为字符串。

动态SQL可能是一个选项,但我想避免动态SQL第二个是可以从第一个派生出来的,因此,将第一个插入临时表并查询可能是一个选项。在这种情况下,它将优化我的代码,但也会影响性能。为什么要避免使用动态SQL?我不能使用VIEW,因为我的where子句中有许多参数。我不能使用函数,因为在这种情况下,我必须在子函数中返回游标,并在主函数中循环它。感谢您的评论,我添加了一些细节。我想简化代码,这样我就不必在这两个语句中编写复杂的where原因。这些问题几乎是一样的。我想我现在明白你的意思了。我使用游标从函数返回这些查询的结果。这个函数是从Java代码中调用的。这就是你要写的吗?是的。请解释-如有必要,请使用伪代码-这两个查询如何适合我,我必须在子函数中返回游标,并在主函数中循环它。这是使用动态SQL的解决方案。我不想使用动态SQLOk,没有动态sql,只是简单的查询,但性能可能会更差。
select object_type,status from 
(select object_type,status, row_number() over( partition by object_type,status order by 1) rn from user_objects /* your_where_clusue */
) where rn = case when 'DISTIINCT'/* <- paramete here :isDistinct */  = 'DISTIINCT' then 1 else rn end;
declare
    v_select varchar2(32767);
    v_where  varchar2(32767);
    v_code   varchar2(32767) := '
            ##SELECT##
            ##WHERE##
    ';
begin
    --Populate the clauses.
    if ... then
        v_select := 'select field_1, field_2, field_3, ... , field_30 from my_table';
    else
        v_select := 'select distinct field_1, field_2, field_8 from my_table';
    end if;

    if ... then
        v_where :=
        q'[
            where field_1 = 'foo'
                and field_2 = :bind1
                ...
        ]';
    else
        v_where :=
        q'[
            where field_2 = 'bar'
                and field_2 = :bind2
                ...
        ]';
    end if;

    --Fill in the code.
    v_code := replace(v_code, '##SELECT##', v_select);
    v_code := replace(v_code, '##WHERE##', v_where);

    --Print the code to check the formatting.  Remove after testing.
    dbms_output.put_line(v_code);

    --Run it.
    execute immediate v_code using ...;
end;
/