【问题标题】:PL SQL loop through list of idsPL SQL 循环遍历 id 列表
【发布时间】:2014-09-27 21:20:36
【问题描述】:

我有一个名字列表。

约翰、山姆、彼得、杰克

我想用上面的每一个作为过滤器查询相同的 sql。每个查询都会给我一个唯一的员工 ID,我想用它来删除其他一些记录。

select emp_id from employee where emp_name like '%john%';

假设对于第一个查询,我得到的 id 为 1001。所以删除查询将如下所示。

delete from account_details where emp_id = 1001;
delete from hr_details where emp_id = 1001;
delete from pay_role_details where emp_id = 1001;

我必须为员工列表重复此操作。伪代码如下所示。

var emp_list = ['john', 'jack', 'kate', 'peter', 'sam',...]

for each :employee_name in emp_list
    select emp_id as :var_emp_id from employee where emp_name like '%:employee_name%'; 

    delete from account_details where emp_id = :var_emp_id;
    delete from hr_details where emp_id = :var_emp_id;
    delete from pay_role_details where emp_id = :var_emp_id;
end loop

我想要一个 PL-SQL 查询来执行此操作。请帮忙。谢谢。

我尝试的是如下所示。

set serveroutput on;
begin
loop x in ('john','jack', 'kate') loop as :name
  select emp_id as var_emp_id from employee where emp_name like '%:name%';
  // delete queries  
end loop;
end;

附:虽然根据提问,like query可能会产生多条记录,但在实际场景中,保证只有一条记录。为什么我使用 like 是在实际场景中,它是参考编号列表而不是名称。参考号还有一些其他的前置文本和后置文本,而我的逗号分隔列表只有数字。

【问题讨论】:

    标签: sql oracle plsql oracle-sqldeveloper plsqldeveloper


    【解决方案1】:

    也许以下会有所帮助:

    BEGIN
      FOR aName IN (SELECT 'john'  AS EMP_NAME FROM DUAL
                    UNION ALL
                    SELECT 'sam'   AS EMP_NAME FROM DUAL
                    UNION ALL
                    SELECT 'peter' AS EMP_NAME FROM DUAL
                    UNION ALL
                    SELECT 'jack'  AS EMP_NAME FROM DUAL)
      LOOP
        FOR emp IN (SELECT * FROM EMPLOYEE WHERE EMP_NAME LIKE '%' || aName.EMP_NAME || '%')
        LOOP
          DELETE FROM ACCOUNT_DETAILS a WHERE a.EMP_ID = emp.EMP_ID;
          DELETE FROM HR_DETAILS h WHERE h.EMP_ID = emp.EMP_ID;
          DELETE FROM PAY_ROLE_DETAILS p WHERE p.EMP_ID = emp.EMP_ID;
    
          DBMS_OUTPUT.PUT_LINE('Deleted data for employee with EMP_ID=' || emp.EMP_ID);
        END LOOP;  -- emp
      END LOOP; -- aName
    END;
    

    研究此内容,直到您了解它的工作原理和原因。

    分享和享受。

    【讨论】:

      【解决方案2】:

      你真的需要一个光标来这样做吗?如果可能,请尝试跳过光标,以避免在大量数据上造成性能/内存使用不佳。

      delete from account_details inner join employee on account_details.emp_id = employee.emp_id where WHERE CONTAINS(employee.emp_name, '"John" OR "Sam" OR "Max"', 1) >0;
      
      delete from hr_details inner join employee on hr_details.emp_id = employee.emp_id where WHERE CONTAINS(employee.emp_name, '"John" OR "Sam" OR "Max"', 1) >0;
      
      delete from pay_role_details inner join employee on pay_role_details.emp_id = employee.emp_id where WHERE CONTAINS(employee.emp_name, '"John" OR "Sam" OR "Max"', 1) >0;
      

      【讨论】:

      • 当然,您本身不需要游标,但是,他特别要求使用 PL/SQL 过程,恕我直言,游标更适合这种情况。但与往常一样,一切都有其优点和缺点。
      • 同意他的标准是否更复杂,需要更多的逻辑来处理。
      【解决方案3】:

      使用 PL/SQL 游标选择您要删除的所有 ID,然后将其循环并在每次传递时发出 DELETE 语句。

      可以在此处找到有关光标的详细信息:http://www.oracle.com/technetwork/issue-archive/2013/13-mar/o23plsql-1906474.html

      动态 SQL 见这里:http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/dynamic.htm#LNPLS627

      代码示例:

          PROCEDURE delete_stuff
          IS
      
          id AS NUMBER;
      
          CURSOR your_cursor IS
          SELECT emp_id FROM employee WHERE CONTAINS(employee.emp_name, '"John" OR "Sam" OR "Max"', 1) > 0;
      
          OPEN your_cursor;
              LOOP
              FETCH your_cursor INTO id;
              EXIT WHEN your_cursor%NOTFOUND;
      
              EXECUTE IMMEDIATE 'DELETE FROM account_details WHERE emp_id = :id' USING id;
              EXECUTE IMMEDIATE 'DELETE FROM hr_details WHERE emp_id = :id' USING id;
              EXECUTE IMMEDIATE 'DELETE FROM pay_role_details WHERE emp_id = :id' USING id;
      
          CLOSE your_cursor;
          END LOOP;
      
          EXCEPTION 
          WHEN OTHERS THEN NULL;
      
      
      END delete_stuff;
      

      【讨论】:

      • 个人喜好。恕我直言,如果您需要调整事物或突然需要满足更复杂的需求,它会更加通用。
      猜你喜欢
      • 2023-03-19
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2021-07-30
      • 2016-07-24
      • 2023-03-28
      • 1970-01-01
      • 2022-11-13
      相关资源
      最近更新 更多