Oracle 其中“从CSV列表中的任何值开始”的条件
可能重复: 我在PL/SQL中有一个查询,它是为处理变量中的输入而构建的,作为一个以筛选器开头的查询:Oracle 其中“从CSV列表中的任何值开始”的条件,oracle,csv,plsql,oracle10g,stringtokenizer,Oracle,Csv,Plsql,Oracle10g,Stringtokenizer,可能重复: 我在PL/SQL中有一个查询,它是为处理变量中的输入而构建的,作为一个以筛选器开头的查询: WHERE product_group LIKE strProductGroup || '%' 作为一项新功能,输入变量可以包含逗号分隔的值。所以,在我期待像艺术这样的东西之前,我现在可以看到艺术,DRM 如果可能的话,我希望避免将此查询构建为字符串并使用executeimmediate。有人能想出一种方法来编写WHERE条件,该条件相当于说以Oracle 10g中CSV列表中的任何值开头
WHERE product_group LIKE strProductGroup || '%'
作为一项新功能,输入变量可以包含逗号分隔的值。所以,在我期待像艺术这样的东西之前,我现在可以看到艺术,DRM
如果可能的话,我希望避免将此查询构建为字符串并使用executeimmediate。有人能想出一种方法来编写WHERE条件,该条件相当于说以Oracle 10g中CSV列表中的任何值开头吗?假设您在创建两个附加对象(集合类型和函数)时没有任何限制,您可以将列表解析为可在查询中引用的集合。汤姆·凯特在他的帖子中对此进行了很好的讨论 例如,如果使用Tom的myTableType和in_list函数
SQL> create or replace type myTableType as table
of varchar2 (255);
2 /
Type created.
ops$tkyte@dev8i> create or replace
function in_list( p_string in varchar2 ) return myTableType
2 as
3 l_string long default p_string || ',';
4 l_data myTableType := myTableType();
5 n number;
6 begin
7 loop
8 exit when l_string is null;
9 n := instr( l_string, ',' );
10 l_data.extend;
11 l_data(l_data.count) :=
ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
12 l_string := substr( l_string, n+1 );
13 end loop;
14
15 return l_data;
16 end;
17 /
然后,您可以相对轻松地搜索相等
WHERE product_group IN (SELECT column_value
FROM TABLE( in_list( strProductGroup )))
但是你想做一个更具挑战性的喜欢,因为你不能在列表中做一个喜欢。然而,你可以这样做
select *
from emp e,
(select '^' || column_value search_regexp
from table( in_list( 'KIN,BOB' ))) a
where regexp_like( e.ename, a.search_regexp )
这将在EMP表中搜索ENAME以KIN或BOB开头的任何员工。在默认的SCOTT.EMP表中,这将只返回一行,即ENAME占主导地位的行。假设您在创建两个附加对象(集合类型和函数)时没有任何限制,您可以将列表解析为一个集合,以便在查询中引用。汤姆·凯特在他的帖子中对此进行了很好的讨论 例如,如果使用Tom的myTableType和in_list函数
SQL> create or replace type myTableType as table
of varchar2 (255);
2 /
Type created.
ops$tkyte@dev8i> create or replace
function in_list( p_string in varchar2 ) return myTableType
2 as
3 l_string long default p_string || ',';
4 l_data myTableType := myTableType();
5 n number;
6 begin
7 loop
8 exit when l_string is null;
9 n := instr( l_string, ',' );
10 l_data.extend;
11 l_data(l_data.count) :=
ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
12 l_string := substr( l_string, n+1 );
13 end loop;
14
15 return l_data;
16 end;
17 /
然后,您可以相对轻松地搜索相等
WHERE product_group IN (SELECT column_value
FROM TABLE( in_list( strProductGroup )))
但是你想做一个更具挑战性的喜欢,因为你不能在列表中做一个喜欢。然而,你可以这样做
select *
from emp e,
(select '^' || column_value search_regexp
from table( in_list( 'KIN,BOB' ))) a
where regexp_like( e.ename, a.search_regexp )
这将在EMP表中搜索ENAME以KIN或BOB开头的任何员工。在默认的SCOTT.EMP表中,这将只返回一行,即ENAME为王的那一行我找到了另一行,这给了我一个想法。在我的特定情况下,输入中的值都是3个字符,因此我可以执行以下操作:
AND SUBSTR(product_group, 0, 3) IN
(SELECT regexp_substr(strProductGroup, '[^,]+', 1, LEVEL)
FROM dual
CONNECT BY LEVEL <= length(regexp_replace(strProductGroup, '[^,]+')) + 1)
我喜欢这个解决方案,因为它不需要额外的类型或函数,但仅限于我的具体情况。我找到了另一个给我一个想法的解决方案。在我的特定情况下,输入中的值都是3个字符,因此我可以执行以下操作:
AND SUBSTR(product_group, 0, 3) IN
(SELECT regexp_substr(strProductGroup, '[^,]+', 1, LEVEL)
FROM dual
CONNECT BY LEVEL <= length(regexp_replace(strProductGroup, '[^,]+')) + 1)
我喜欢此解决方案,因为它不需要额外的类型或功能,但仅限于我的具体情况。也许您希望在strProductGroup?中使用product_group?而不是重复。另一个帖子是关于11g的,我也有关于需求的开头。也许你想在strProductGroup中使用product_group?不是重复的。另一个帖子是关于11g的,我也有关于需求的开头。添加一个管道将非常方便,不是吗?@gpeche-这不会有什么坏处。但是,假设字符串适合VARCHAR2,那么它的大小限制为32k。如果每个搜索项为3个字节,逗号为第4个字节,则表示最多有8k个搜索项。这是一个集合中元素数量相当合理的集合,无需通过管道传输结果。管道化结果不会有什么坏处,但它确实增加了一些复杂性。此外,重要的是要记住查看执行计划,因为一些Oracle版本对表类型非常困惑。有时你需要添加一个基数或具体化提示来让Oracle做正确的事情。添加一个流水线将非常方便,不是吗?@gpeche-这不会有什么坏处。但是,假设字符串适合VARCHAR2,那么它的大小限制为32k。如果每个搜索项为3个字节,逗号为第4个字节,则表示最多有8k个搜索项。这是一个集合中元素数量相当合理的集合,无需通过管道传输结果。管道化结果不会有什么坏处,但它确实增加了一些复杂性。此外,重要的是要记住查看执行计划,因为一些Oracle版本对表类型非常困惑。有时,您需要添加基数或具体化提示,以使Oracle做正确的事情。