You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle PL/SQL存储过程:如何正确检索含多值的员工姓名匹配记录

解决Oracle Employee表多姓名值的检索存储过程问题

我来帮你搞定这个多姓名匹配的问题!你的核心痛点是原存储过程只会匹配单条姓名的记录,没法处理用分号分隔的多姓名行。咱们先理清楚问题,再给出修正后的方案。

问题梳理

你有一个Employee表,Name列要么是单个姓名(格式:名 姓 (用户名)),要么是多个用分号分隔的这类姓名串。需要实现:

  • 按名检索:输入长度至少2字符,匹配姓名开头的名
  • 按姓检索:输入长度至少2字符,匹配姓名里的姓
  • 按用户名检索:必须输入完整内容,匹配括号里的用户名

现有表数据

IDNameTitle
1Andrea Warbutton (awr01)Manager
2Claire Taylor (cta02);Mark Kites (mak03);Anitha Rooney (anr06)HOD;Supervisor;Business
3Dave Rites (dar12);Jessica Simpson (jesi10)Lead;Analyst
4Nick Ken (nik56)Product (Local,Regional)
5Claire Pilkington (cpt09)Sales Owner

原代码的问题

原存储过程不仅语法有错误(比如CREATE OR REPLACE后面缺PROCEDURE、INSTR参数写错、字符串拼接多了空的||),更关键的是它直接对整列Name做匹配,没法拆分多值行里的单个姓名项,所以只能命中单值的记录。原错误代码如下:

-- 原代码存在语法错误,且无法处理多值行
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 ||'%'||) -- 语法错误:多余的||
OR Upper(SUBSTR(Name, INSTR(Name),' '+1)) like Upper(pm_lastname ||'%'||) -- 语法错误:INSTR参数顺序错,多余的||
OR upper(REGEXP_SUBSTR(Name,'\((.+)\)',1,1,NULL,1)) = Upper(pm_username); -- 只提取第一个用户名
END;
End empl ;

解决方案:拆分多值行后匹配

核心思路是先用Oracle的CONNECT BY+REGEXP_SUBSTR把多值的Name和Title拆分成单行(保证每个姓名对应其职位),再对拆分后的单个姓名做匹配。

修正后的存储过程

CREATE OR REPLACE PROCEDURE empl(
    pm_firstname VARCHAR2,
    pm_lastname VARCHAR2,
    pm_username VARCHAR2
)
IS
BEGIN
    -- 拆分多值字段为单行,再进行精准匹配
    SELECT 
        e.ID,
        split_name.name_part,
        split_title.title_part
    FROM Employee e
    -- 拆分Name字段为单个姓名行
    CROSS JOIN TABLE(
        CAST(
            MULTISET(
                SELECT REGEXP_SUBSTR(e.Name, '[^;]+', 1, LEVEL)
                FROM DUAL
                CONNECT BY REGEXP_SUBSTR(e.Name, '[^;]+', 1, LEVEL) IS NOT NULL
            ) AS SYS.ODCIVARCHAR2LIST
        )
    ) split_name
    -- 拆分Title字段为对应职位行,和姓名一一对应
    CROSS JOIN TABLE(
        CAST(
            MULTISET(
                SELECT REGEXP_SUBSTR(e.Title, '[^;]+', 1, LEVEL)
                FROM DUAL
                CONNECT BY REGEXP_SUBSTR(e.Title, '[^;]+', 1, LEVEL) IS NOT NULL
            ) AS SYS.ODCIVARCHAR2LIST
        )
    ) split_title
    -- 确保拆分的姓名和职位是同一索引(对应同一人员)
    WHERE split_name.COLUMN_VALUE = REGEXP_SUBSTR(e.Name, '[^;]+', 1, split_title.COLUMN_VALUE)
    AND (
        -- 名匹配:输入长度≥2,匹配姓名开头的第一个单词
        (pm_firstname IS NOT NULL AND LENGTH(pm_firstname) >= 2 
         AND UPPER(REGEXP_SUBSTR(split_name.name_part, '^\w+')) LIKE UPPER(pm_firstname || '%'))
        -- 姓匹配:输入长度≥2,匹配姓名里的第二个单词
        OR (pm_lastname IS NOT NULL AND LENGTH(pm_lastname) >= 2 
            AND UPPER(REGEXP_SUBSTR(split_name.name_part, '\w+', 1, 2)) LIKE UPPER(pm_lastname || '%'))
        -- 用户名匹配:输入完整内容,匹配括号内的字符串
        OR (pm_username IS NOT NULL 
            AND UPPER(REGEXP_SUBSTR(split_name.name_part, '\((.+)\)', 1, 1, NULL, 1)) = UPPER(pm_username))
    )
    ORDER BY e.ID;
END empl;
/

关键优化说明

  1. 拆分多值字段:用CONNECT BY循环拆分分号分隔的内容,把多值行拆成单行记录,让每个姓名单独参与匹配
  2. 职位关联:同步拆分Title字段,通过索引关联保证每个姓名对应正确的职位
  3. 输入校验:添加了名和姓的长度校验(≥2字符),符合你的需求
  4. 精准匹配:对拆分后的单个姓名提取名、姓、用户名,而非原整列匹配,解决多值行的匹配问题

测试验证(和你的期望完全一致)

  1. 搜索firstname = "Andrea"

    IDname_parttitle_part
    1Andrea Warbutton (awr01)Manager
  2. 搜索firstname = "Claire"

    IDname_parttitle_part
    2Claire Taylor (cta02)HOD
    5Claire Pilkington (cpt09)Sales Owner
  3. 搜索lastname = "Simps"

    IDname_parttitle_part
    3Jessica Simpson (jesi10)Analyst
  4. 搜索username = "mak03"

    IDname_parttitle_part
    2Mark Kites (mak03)Supervisor
  5. 搜索username = "nik56"

    IDname_parttitle_part
    4Nick Ken (nik56)Product (Local,Regional)

内容的提问来源于stack exchange,提问作者Anitha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 09:33:11