我有两种类型的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。
有什么建议吗?
答案 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对这些高级功能没有很好的支持,因此将代码构建为字符串通常会更好。