具有相同where子句

时间:2017-07-20 13:45:28

标签: oracle plsql where-clause code-design

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

One - 返回交易详细数据

select field_1, field_2, field_3, ... , field_30 from my_table where my_where_clause

第二 - 返回由(不同)商家分组的交易数据

select distinct field_1, field_2, field_8 from my_table where my_where_clause

声明单独调用。

我想简化我的代码,不要在两个语句中重复这个复杂的where子句而不会失去性能

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

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

建议:您可以尝试使用GROUPING SETS表达式。  它允许您有选择地指定要在GROUP BY子句中创建的组的集合。在

在您的情况下,您可以指定2组,为1到30的所有字段设置一组,为字段1,2和8设置另一组。  链接 - https://docs.oracle.com/cd/E40518_01/server.761/es_eql/src/reql_aggregation_grouping_sets.html

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

答案 1 :(得分:1)

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

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;

答案 2 :(得分:0)

你说你在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;

答案 3 :(得分:0)

通过使用多行字符串,备用引号和模板,可以使动态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对这些高级功能没有很好的支持,因此将代码构建为字符串通常会更好。