我是Oracle PL / SQL的新手,但在Sql Server中经验丰富,我正在努力学习它的来龙去脉。为了介绍它,我决定优化一个生成为C#字符串的查询,然后作为文本SqlCommand执行。所以我试图创建一个存储过程,但是要包含where子句如何生成的所有变量,它会导致它运行~40秒,同时C#生成的字符串在~3秒内执行。以下是where子句变体的含义示例...
declare
searchType nvarchar2(3); -- options are 'x', 'y', 'z'
searchDesc nvarchar2(4); -- options are '1', '2', '3'
searchValue nvarchar2(5);
begin
select count(*)
from tbl_A a
where ((searchType = 'x'
and ((a.desc_X = searchDesc and a.value_1 = searchValue)
or (a.desc_X = searchDesc and a.value_2 = searchValue)
or (a.desc_X = searchDesc and a.value_3 = searchValue)
)
)
or (searchType = 'y'
and ((a.desc_Y = searchDesc and a.value_1 = searchValue)
or (a.desc_Y = searchDesc and a.value_2 = searchValue)
or (a.desc_Y = searchDesc and a.value_3 = searchValue)
)
)
or (searchType = 'z'
and ((a.desc_Z = searchDesc and a.value_1 = searchValue)
or (a.desc_Z = searchDesc and a.value_2 = searchValue)
or (a.desc_Z = searchDesc and a.value_3 = searchValue)
)
)
)
end;
所以我想知道的是,是否有可能在where子句中有一个可以执行动态sql的select语句。或者整个语句需要是动态sql。以下是我正在质疑的一个例子......
declare
whereClause varchar2(500);
searchType nvarchar2(3); -- options are 'x', 'y', 'z'
searchDesc nvarchar2(4); -- options are '1', '2', '3'
searchValue nvarchar2(5);
begin
select case
when searchType = 'x' then 'a.desc_X = :desc and a.value_1 = :val'
when searchType = 'y' then 'a.desc_Y = :desc and a.value_2 = :val'
when searchType = 'z' then 'a.desc_Z = :desc and a.value_3 = :val'
end
into whereClause
from dual;
select count(*)
from tbl_A a
where (
execute immediately whereClause using searchDesc, searchValue
)
end;
当我尝试将其作为所有动态sql执行时,它仍然需要大约15秒才能执行。因此,如果有人有更好的方法来处理许多where子句的变化,我愿意接受建议。
答案 0 :(得分:2)
使用过多的OR会导致性能下降。如果你总是要有一组固定的参数,你可以这样做:
declare
stmt varchar2(1500);
searchType nvarchar2(3); -- options are 'x', 'y', 'z'
searchDesc nvarchar2(4); -- options are '1', '2', '3'
searchValue nvarchar2(5);
n pls_integer;
begin
stmt := 'select count(*) from tbl_A a where (';
case
when searchType = 'x' then stmt := stmt || 'a.desc_X = :desc and a.value_1 = :val';
when searchType = 'y' then stmt := stmt || 'a.desc_Y = :desc and a.value_2 = :val';
when searchType = 'z' then stmt := stmt || 'a.desc_Z = :desc and a.value_3 = :val';
end case;
stmt := stmt ||')';
execute immediately stmt using searchDesc, searchValue
into n;
end;
请注意 - 与T-SQL不同 - 在PL / SQL中,我们需要将结果集选择为变量。我提出了一个整数,因为你的示例代码只是SELECT COUNT(*)。您的真实查询将需要一个与查询投影匹配的变量,可能是记录类型或集合。