如何在oracle plsql中的存储过程中过滤和检索特定字符后的结果?
How to filter and retrieve the results after a Specific characters from stored procedure in oracle plsql?
我在“员工”table 中有一列“姓名”,它具有以下值。这些值要么仅包含单个名称(名字、姓氏、用户名),要么包含多个名称,并以分号 (;) 分隔。我需要通过名字、姓氏或用户名从 table 中搜索值。
我创建了一个过程,但它只获取第 1、4、5 条记录。请让我知道如何检索第二条和第三条记录。
名字和姓氏可以由用户给出,长度至少为 2 个字符。
用户名是完整的。
员工:
ID Name Title
1 Andrea Warbutton (awr01) Manager
2 Claire Taylor (cta02);Mark Kites (mak03);Anitha Rooney (anr06) HOD;Supervisor;Business
3 Dave Rites (dar12);Jessica Simpson (jesi10) Lead;Analyst
4 Nick Ken (nik56) Product (Local,Regional)
5 Claire Pilkington (cpt09) Sales Owner
代码:
Create or replace empl (pm_firstname varchar2(100),
pm_lastname varchar2(100),
pm_username varchar2(100))
BEGIN
Select * from Employee
where Upper(Name) like Upper(pm_firstname ||'%'||) -- this will fetch 1st,4th,5th record
OR Upper(SUBSTR(Name, INSTR(Name),' '+1)) like Upper(pm_lastname ||'%'||) -- this will fetch 1st,4th,5th record
OR upper(REGEXP_SUBSTR(Name,'\((.+)\)',1,1,NULL,1)) = Upper(pm_username); -- -- this will fetch 1st,4th,5th record
END;
End empl ;
请告诉我如何检索第 2 条和第 3 条记录。
期望输出:
当使用 firstname = "Andrea" 搜索时,输出如下
ID Name Title
1 Andrea Warbutton (awr01) Manager
当使用 firstname = "Claire" 搜索时,输出如下
ID Name Title
2 Claire Taylor (cta02) HOD
5 Claire Pilkington (cpt09) Sales Owner
当搜索 lastname = "Simps" 时,输出如下
ID Name Title
3 Jessica Simpson (jesi10) Analyst
使用用户名 = "mak03" 搜索时,输出如下
ID Name Title
2 Mark Kites (mak03) Supervisor
使用用户名 = "nik56" 搜索时,输出如下
ID Name Title
4 Nick Ken (nik56) Product (Local,Regional)
不需要PL/SQL。
SQL> with temp as
2 (select id,
3 regexp_substr(name, '[^;]+', 1, column_value) name
4 from employee cross join
5 table(cast(multiset(select level from dual
6 connect by level <= regexp_count(name, ';') + 1
7 ) as sys.odcinumberlist))
8 )
9 select id, name
10 from temp
11 where instr(name, '&search_for_name') > 0;
Enter value for search_for_name: Claire
ID NAME
---------- ------------------------------
2 Claire Taylor (cta02)
5 Claire Pilkington (cpt09)
SQL> /
Enter value for search_for_name: mak03
ID NAME
---------- ------------------------------
2 Mark Kites (mak03)
SQL>
它有什么作用?
temp
CTE 将分号分隔的值拆分成行
- 最终查询使用一个简单的
instr
函数来检测“行”(之前提取的)是否包含您要查找的值
如果它必须是一个函数,则可以重用该代码。由于您没有说出您想要 return 的确切内容(我的意思是哪种数据类型),我 return 编辑了一个字符串。
SQL> create or replace function f_search (par_what in varchar2)
2 return sys.odcivarchar2list
3 is
4 retval sys.odcivarchar2list;
5 begin
6 with temp as
7 (select id,
8 regexp_substr(name, '[^;]+', 1, column_value) name
9 from employee cross join
10 table(cast(multiset(select level from dual
11 connect by level <= regexp_count(name, ';') + 1
12 ) as sys.odcinumberlist))
13 )
14 select id ||' - '|| name
15 bulk collect into retval
16 from temp
17 where instr(name, par_what) > 0;
18
19 return retval;
20 end;
21 /
Function created.
SQL> select * from table(f_search('Andrea'));
COLUMN_VALUE
--------------------------------------------------------------------------------
1 - Andrea Warbutton (awr01)
SQL> select * from table(f_search('Claire'));
COLUMN_VALUE
--------------------------------------------------------------------------------
2 - Claire Taylor (cta02)
5 - Claire Pilkington (cpt09)
SQL>
with
x as (select id, name, '"'||replace(name, ';', '","')||'"' xml from employee),
n as (select id, name, column_value as cv from x, xmltable(xml))
select id,
trim(regexp_substr(cv, '(\S*)(\s)')) fname,
trim(regexp_substr(cv, '(\S*)(\s)', 1, 2)) lname,
regexp_substr(cv, '\((.+)\)', 1, 1, NULL, 1) uname
from n
如果将这些数据标准化,您的任务会容易得多。以上查询输出:
ID FNAME LNAME UNAME
1 Andrea Warbutton awr01
2 Claire Taylor cta02
2 Mark Kites mak03
2 Anitha Rooney anr06
3 Dave Rites dar12
3 Jessica Simpson jesi10
4 Nick Ken nik56
5 Claire Pilkington cpt09
现在您可以根据需要搜索第一个、最后一个用户名。第一个表达式找到第一个词,然后是第二个和 .
编辑:
I posted the table structure with just ID and Name columns. However, I
have Titles column also in the same format separated with (semicolon).
In this case, How can I Normalize Titles as well along with Names
此查询适用于提供的示例:
with
x as (select id, name, '"'||replace(name, ';', '","')||'"' xmln,
'"'||replace(title, ';', '","')||'"' xmlt
from employee),
n1 as (select id, trim(xn.column_value) nm, rownum rn from x, xmltable(xmln) xn),
n2 as (select id, trim(xt.column_value) tt, rownum rn from x, xmltable(xmlt) xt)
select id, trim(regexp_substr(nm, '(\S*)(\s)')) fname,
trim(regexp_substr(nm, '(\S*)(\s)', 1, 2)) lname,
regexp_substr(nm, '\((.+)\)', 1, 1, NULL, 1) uname,
tt title
from n1 join n2 using (id, rn)
但是要小心,因为我们无法编写理想的查询。如果您有像 Benicio Del Toro、Mary Jo Catlett、Jean Claude Van Damme 这样的条目,则不可能编写正确的正则表达式。有时第二个词是姓氏的一部分,有时是名字、中间名等。
正确的方法是修改 table 结构,划分行,检查结果并将正确的值放入正确的名称列中。现在您有难以搜索的列表,并且每种方法都可能 return 错误的结果。
我在“员工”table 中有一列“姓名”,它具有以下值。这些值要么仅包含单个名称(名字、姓氏、用户名),要么包含多个名称,并以分号 (;) 分隔。我需要通过名字、姓氏或用户名从 table 中搜索值。
我创建了一个过程,但它只获取第 1、4、5 条记录。请让我知道如何检索第二条和第三条记录。
名字和姓氏可以由用户给出,长度至少为 2 个字符。 用户名是完整的。
员工:
ID Name Title
1 Andrea Warbutton (awr01) Manager
2 Claire Taylor (cta02);Mark Kites (mak03);Anitha Rooney (anr06) HOD;Supervisor;Business
3 Dave Rites (dar12);Jessica Simpson (jesi10) Lead;Analyst
4 Nick Ken (nik56) Product (Local,Regional)
5 Claire Pilkington (cpt09) Sales Owner
代码:
Create or replace empl (pm_firstname varchar2(100),
pm_lastname varchar2(100),
pm_username varchar2(100))
BEGIN
Select * from Employee
where Upper(Name) like Upper(pm_firstname ||'%'||) -- this will fetch 1st,4th,5th record
OR Upper(SUBSTR(Name, INSTR(Name),' '+1)) like Upper(pm_lastname ||'%'||) -- this will fetch 1st,4th,5th record
OR upper(REGEXP_SUBSTR(Name,'\((.+)\)',1,1,NULL,1)) = Upper(pm_username); -- -- this will fetch 1st,4th,5th record
END;
End empl ;
请告诉我如何检索第 2 条和第 3 条记录。
期望输出:
当使用 firstname = "Andrea" 搜索时,输出如下
ID Name Title
1 Andrea Warbutton (awr01) Manager
当使用 firstname = "Claire" 搜索时,输出如下
ID Name Title
2 Claire Taylor (cta02) HOD
5 Claire Pilkington (cpt09) Sales Owner
当搜索 lastname = "Simps" 时,输出如下
ID Name Title
3 Jessica Simpson (jesi10) Analyst
使用用户名 = "mak03" 搜索时,输出如下
ID Name Title
2 Mark Kites (mak03) Supervisor
使用用户名 = "nik56" 搜索时,输出如下
ID Name Title
4 Nick Ken (nik56) Product (Local,Regional)
不需要PL/SQL。
SQL> with temp as
2 (select id,
3 regexp_substr(name, '[^;]+', 1, column_value) name
4 from employee cross join
5 table(cast(multiset(select level from dual
6 connect by level <= regexp_count(name, ';') + 1
7 ) as sys.odcinumberlist))
8 )
9 select id, name
10 from temp
11 where instr(name, '&search_for_name') > 0;
Enter value for search_for_name: Claire
ID NAME
---------- ------------------------------
2 Claire Taylor (cta02)
5 Claire Pilkington (cpt09)
SQL> /
Enter value for search_for_name: mak03
ID NAME
---------- ------------------------------
2 Mark Kites (mak03)
SQL>
它有什么作用?
temp
CTE 将分号分隔的值拆分成行- 最终查询使用一个简单的
instr
函数来检测“行”(之前提取的)是否包含您要查找的值
如果它必须是一个函数,则可以重用该代码。由于您没有说出您想要 return 的确切内容(我的意思是哪种数据类型),我 return 编辑了一个字符串。
SQL> create or replace function f_search (par_what in varchar2)
2 return sys.odcivarchar2list
3 is
4 retval sys.odcivarchar2list;
5 begin
6 with temp as
7 (select id,
8 regexp_substr(name, '[^;]+', 1, column_value) name
9 from employee cross join
10 table(cast(multiset(select level from dual
11 connect by level <= regexp_count(name, ';') + 1
12 ) as sys.odcinumberlist))
13 )
14 select id ||' - '|| name
15 bulk collect into retval
16 from temp
17 where instr(name, par_what) > 0;
18
19 return retval;
20 end;
21 /
Function created.
SQL> select * from table(f_search('Andrea'));
COLUMN_VALUE
--------------------------------------------------------------------------------
1 - Andrea Warbutton (awr01)
SQL> select * from table(f_search('Claire'));
COLUMN_VALUE
--------------------------------------------------------------------------------
2 - Claire Taylor (cta02)
5 - Claire Pilkington (cpt09)
SQL>
with
x as (select id, name, '"'||replace(name, ';', '","')||'"' xml from employee),
n as (select id, name, column_value as cv from x, xmltable(xml))
select id,
trim(regexp_substr(cv, '(\S*)(\s)')) fname,
trim(regexp_substr(cv, '(\S*)(\s)', 1, 2)) lname,
regexp_substr(cv, '\((.+)\)', 1, 1, NULL, 1) uname
from n
如果将这些数据标准化,您的任务会容易得多。以上查询输出:
ID FNAME LNAME UNAME
1 Andrea Warbutton awr01
2 Claire Taylor cta02
2 Mark Kites mak03
2 Anitha Rooney anr06
3 Dave Rites dar12
3 Jessica Simpson jesi10
4 Nick Ken nik56
5 Claire Pilkington cpt09
现在您可以根据需要搜索第一个、最后一个用户名。第一个表达式找到第一个词,然后是第二个和
编辑:
I posted the table structure with just ID and Name columns. However, I have Titles column also in the same format separated with (semicolon). In this case, How can I Normalize Titles as well along with Names
此查询适用于提供的示例:
with
x as (select id, name, '"'||replace(name, ';', '","')||'"' xmln,
'"'||replace(title, ';', '","')||'"' xmlt
from employee),
n1 as (select id, trim(xn.column_value) nm, rownum rn from x, xmltable(xmln) xn),
n2 as (select id, trim(xt.column_value) tt, rownum rn from x, xmltable(xmlt) xt)
select id, trim(regexp_substr(nm, '(\S*)(\s)')) fname,
trim(regexp_substr(nm, '(\S*)(\s)', 1, 2)) lname,
regexp_substr(nm, '\((.+)\)', 1, 1, NULL, 1) uname,
tt title
from n1 join n2 using (id, rn)
但是要小心,因为我们无法编写理想的查询。如果您有像 Benicio Del Toro、Mary Jo Catlett、Jean Claude Van Damme 这样的条目,则不可能编写正确的正则表达式。有时第二个词是姓氏的一部分,有时是名字、中间名等。 正确的方法是修改 table 结构,划分行,检查结果并将正确的值放入正确的名称列中。现在您有难以搜索的列表,并且每种方法都可能 return 错误的结果。