Oracle EBS 实战:调用 API 创建员工及 ORA-20001 报错解析

Administrator
发布于 2026-01-12 / 9 阅读
1
0

Oracle EBS 实战:调用 API 创建员工及 ORA-20001 报错解析

1. 业务背景

在 Oracle EBS HRMS 开发中,通过程序批量导入员工是核心业务场景。相比直接操作基表,调用标准 API hr_employee_api.create_employee 能够自动处理复杂的业务逻辑校验。

2. 核心代码实现

以下是一个完整的 PL/SQL 调用示例,包含了必要的变量定义和异常处理逻辑:

SQL

DECLARE
  -- 定义变量
  LC_EMPLOYEE_NUMBER   PER_ALL_PEOPLE_F.EMPLOYEE_NUMBER%TYPE;
  LN_PERSON_ID         PER_ALL_PEOPLE_F.PERSON_ID%TYPE;
  LN_ASSIGNMENT_ID     PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_ID%TYPE;
  LN_OBJECT_VER_NUMBER PER_ALL_ASSIGNMENTS_F.OBJECT_VERSION_NUMBER%TYPE;
  ln_asg_ovn           NUMBER := 5;

  LD_PER_EFFECTIVE_START_DATE PER_ALL_PEOPLE_F.EFFECTIVE_START_DATE%TYPE;
  LD_PER_EFFECTIVE_END_DATE   PER_ALL_PEOPLE_F.EFFECTIVE_END_DATE%TYPE := NULL;
  LC_FULL_NAME                PER_ALL_PEOPLE_F.FULL_NAME%TYPE;
  LN_PER_COMMENT_ID           PER_ALL_PEOPLE_F.COMMENT_ID%TYPE := NULL;
  LN_ASSIGNMENT_SEQUENCE      PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_SEQUENCE%TYPE;
  lc_assignment_number        PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_NUMBER%TYPE;

  LB_NAME_COMBINATION_WARNING BOOLEAN;
  LB_ASSIGN_PAYROLL_WARNING   BOOLEAN;
  LB_ORIG_HIRE_WARNING        BOOLEAN;
  
  p_number varchar2(100) := 'test2019041'; -- 测试工号

BEGIN
  -- 调用创建员工 API
  hr_employee_api.create_employee(
      p_person_type_id            => 6, -- 需注意环境差异
      p_hire_date                 => TO_DATE('2019-04-01','YYYY-MM-DD'),
      P_BUSINESS_GROUP_ID         => 0,
      P_LAST_NAME                 => '王十',
      P_FIRST_NAME                => NULL,
      p_sex                       => 'M',
      p_employee_number           => p_number,
      -- 输出参数
      p_person_id                 => ln_person_id,
      p_assignment_id             => ln_assignment_id,
      p_per_object_version_number => ln_object_ver_number,
      p_asg_object_version_number => ln_asg_ovn,
      p_per_effective_start_date  => ld_per_effective_start_date,
      p_per_effective_end_date    => ld_per_effective_end_date,
      p_full_name                 => lc_full_name,
      p_per_comment_id            => ln_per_comment_id,
      p_assignment_sequence       => ln_assignment_sequence,
      p_assignment_number         => lc_assignment_number,
      p_name_combination_warning  => lb_name_combination_warning,
      p_assign_payroll_warning    => lb_assign_payroll_warning,
      p_orig_hire_warning         => lb_orig_hire_warning
  );

  dbms_output.put_line('创建成功,Person ID: ' || ln_person_id);
  -- COMMIT; -- 建议正式环境取消注释
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
    dbms_output.put_line('错误信息: ' || SQLERRM);
END;

3. 常见坑点:ORA-20001 报错解析

在执行上述脚本时,常会遇到以下错误:

ORA-20001: A person type with a system person type EMP must be specified.

原因分析

这是由于 p_person_type_id 参数传入的 ID 在当前 Business Group 下不属于系统定义的 'EMP' 类型。不同环境下的 ID 往往不同,硬编码 ID(如示例中的 6)极易引发此报错。

解决方案

建议通过动态查询获取 ID,增强代码的可移植性:

SQL

DECLARE
  -- 1. 定义 API 所需的输入输出变量
  LC_EMPLOYEE_NUMBER          PER_ALL_PEOPLE_F.EMPLOYEE_NUMBER%TYPE;
  LN_PERSON_ID                PER_ALL_PEOPLE_F.PERSON_ID%TYPE;
  LN_ASSIGNMENT_ID            PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_ID%TYPE;
  LN_OBJECT_VER_NUMBER        PER_ALL_PEOPLE_F.OBJECT_VERSION_NUMBER%TYPE;
  ln_asg_ovn                  NUMBER;
  
  LD_PER_EFFECTIVE_START_DATE PER_ALL_PEOPLE_F.EFFECTIVE_START_DATE%TYPE;
  LD_PER_EFFECTIVE_END_DATE   PER_ALL_PEOPLE_F.EFFECTIVE_END_DATE%TYPE;
  LC_FULL_NAME                PER_ALL_PEOPLE_F.FULL_NAME%TYPE;
  LN_PER_COMMENT_ID           PER_ALL_PEOPLE_F.COMMENT_ID%TYPE;
  LN_ASSIGNMENT_SEQUENCE      PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_SEQUENCE%TYPE;
  lc_assignment_number        PER_ALL_ASSIGNMENTS_F.ASSIGNMENT_NUMBER%TYPE;

  LB_NAME_COMBINATION_WARNING BOOLEAN;
  LB_ASSIGN_PAYROLL_WARNING   BOOLEAN;
  LB_ORIG_HIRE_WARNING        BOOLEAN;

  -- 2. 核心参数变量
  p_number            VARCHAR2(100) := 'test2019041';
  l_business_group_id NUMBER := 0; -- 请根据实际 BG ID 修改
  l_person_type_id    NUMBER;
  l_user_id           NUMBER;
  l_resp_id           NUMBER;
  l_resp_appl_id      NUMBER;

BEGIN
  -- 3. 初始化环境上下文 (非常重要)
  -- 替换下方的 ID 为你环境中的有效值(可通过 FND_USER 和 FND_RESPONSIBILITY 查看)
  SELECT user_id INTO l_user_id FROM fnd_user WHERE user_name = 'OPERATIONS'; -- 示例用户
  SELECT responsibility_id, application_id 
    INTO l_resp_id, l_resp_appl_id 
    FROM fnd_responsibility_vl 
   WHERE responsibility_name = 'US HRMS Manager'; -- 示例职责

  fnd_global.apps_initialize(user_id      => l_user_id,
                             resp_id      => l_resp_id,
                             resp_appl_id => l_resp_appl_id);

  -- 4. 【核心修复】动态获取系统类型为 'EMP' 的人员类型 ID
  -- 解决 ORA-20001: A person type with a system person type EMP must be specified.
  BEGIN
    SELECT person_type_id
      INTO l_person_type_id
      FROM per_person_types
     WHERE business_group_id = l_business_group_id
       AND system_person_type = 'EMP'
       AND active_flag = 'Y'
       AND default_flag = 'Y';
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      raise_application_error(-20001, '无法找到默认的员工(EMP)人员类型,请检查 Business Group 配置。');
  END;

  -- 5. 执行创建员工 API
  hr_employee_api.create_employee(
      p_person_type_id            => l_person_type_id, -- 动态获取的 ID
      p_hire_date                 => TO_DATE('2019-04-01', 'YYYY-MM-DD'),
      p_business_group_id         => l_business_group_id,
      p_last_name                 => '王十',
      p_first_name                => NULL,
      p_sex                       => 'M',
      p_employee_number           => p_number,
      -- 输出参数
      p_person_id                 => ln_person_id,
      p_assignment_id             => ln_assignment_id,
      p_per_object_version_number => ln_object_ver_number,
      p_asg_object_version_number => ln_asg_ovn,
      p_per_effective_start_date  => ld_per_effective_start_date,
      p_per_effective_end_date    => ld_per_effective_end_date,
      p_full_name                 => lc_full_name,
      p_per_comment_id            => ln_per_comment_id,
      p_assignment_sequence       => ln_assignment_sequence,
      p_assignment_number         => lc_assignment_number,
      p_name_combination_warning  => lb_name_combination_warning,
      p_assign_payroll_warning    => lb_assign_payroll_warning,
      p_orig_hire_warning         => lb_orig_hire_warning
  );

  -- 6. 输出结果
  DBMS_OUTPUT.PUT_LINE('创建成功!');
  DBMS_OUTPUT.PUT_LINE('Person ID: ' || ln_person_id);
  DBMS_OUTPUT.PUT_LINE('Full Name: ' || lc_full_name);

  -- COMMIT; -- 确认数据无误后取消注释进行提交

EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
    DBMS_OUTPUT.PUT_LINE('错误代码: ' || SQLCODE);
    DBMS_OUTPUT.PUT_LINE('错误消息: ' || SQLERRM);
END;

错误代码: -20001

错误消息: ORA-20001: You are no longer permitted to enter a number for this person. Please close and reopen the application window you are using. If you are using an API then please rerun the script that calls the API. Doing this enables the application to generate a sequential number automatically.

清空指定员工编号,让系统自动生成

将p_number VARCHAR2(100) := 'test2019041';改为p_number VARCHAR2(100) := null;后创建成功。


评论