【问题标题】:how to execute delete statement inside plsql block and call it in a procedure如何在plsql块中执行删除语句并在过程中调用它
【发布时间】:2019-11-21 10:48:11
【问题描述】:

我已经写在 pl sql 块下面并尝试创建一个程序。但是我收到警告并且无法执行该程序。

如果我遗漏了什么,请提出建议\

如果这个问题重复,请告诉我,因为我无法获得确切的参考链接

create or replace PROCEDURE EmployeeProc
IS 
BEGIN
delete from Employeetable where EmplId in (
select EmployeeId FROM EmployeeMstrTbl where JoiningDate between to_date('2019-01-01','YYYY-MM-DD') and to_date('2019-02-28','YYYY-MM-DD'));
commit;
DBMS_OUTPUT.PUT_LINE('Deleted '||SQL%ROWCOUNT ||' records from Employeetable');
END;

Error: Object Invalid

【问题讨论】:

  • 你能告诉我们编译时引发的实际错误吗?
  • @Tejash .. 感谢您的回复。我收到错误:“程序无效”,在创建程序时我收到警告..
  • 可以发show error,告诉我们你得到了什么。

标签: oracle stored-procedures plsql


【解决方案1】:

尝试使用光标

CREATE OR REPLACE PROCEDURE EMPLOYEEPROC IS 
CURSOR C1 IS 
SELECT EMPLOYEEID 
FROM EMPLOYEEMSTRTBL 
WHERE JOININGDATE BETWEEN TO_DATE('2019-01-01','YYYY-MM-DD') AND TO_DATE('2019-02-28','YYYY-MM-DD'));
BEGIN
    FOR I IN C1 LOOP        
        DELETE FROM EMPLOYEETABLE 
        WHERE EMPLID=I.EMPLOYEEID;
    END LOOP;

    COMMIT;

    DBMS_OUTPUT.PUT_LINE('DELETED '||SQL%ROWCOUNT ||' RECORDS FROM EMPLOYEETABLE');

END;

【讨论】:

    【解决方案2】:

    您的代码运行良好。

    CREATE TABLE Employeetable
    (
        EmplId NUMBER
    );
    
    CREATE TABLE EmployeeMstrTbl
    (
        EmployeeId NUMBER,
        JoiningDate DATE
    );
    
    CREATE OR REPLACE PROCEDURE EmployeeProc
    IS
    BEGIN
        DELETE FROM Employeetable
              WHERE EmplId IN
                        (SELECT EmployeeId
                           FROM EmployeeMstrTbl
                          WHERE JoiningDate BETWEEN TO_DATE ('2019-01-01',
                                                             'YYYY-MM-DD')
                                                AND TO_DATE ('2019-02-28',
                                                             'YYYY-MM-DD'));
    
        COMMIT;
        DBMS_OUTPUT.PUT_LINE (
            'Deleted ' || SQL%ROWCOUNT || ' records from Employeetable');
    END;
    
    EXEC EmployeeProc;
    
    DROP TABLE Employeetable;
    DROP TABLE EmployeeMstrTbl;
    DROP PROCEDURE EmployeeProc;
    

    脚本输出:

    Table created.
    Table created.
    Procedure created.
     PL/SQL procedure successfully completed.
    Table dropped.
    Table dropped.
    Procedure dropped.
    

    DBMS 输出:

    Deleted 0 records from Employeetable
    

    也许您在表名、列名或类似名称中有拼写错误。

    我建议你先尝试执行你的删除语句,看看它是否有效。

    【讨论】:

      【解决方案3】:

      不确定您是否打错了某些内容,或者是否与您的设置方式有关。但即使它是一个错误的类型并且它可以工作,它也不是很好,所以做一个循环。

      i = 0;
      FOR r in (select * FROM EmployeeMstrTbl where JoiningDate between to_date('2019-01-01','YYYY-MM-DD') and to_date('2019-02-28','YYYY-MM-DD'))
        LOOP
        DELETE FROM Employeetable where EmplId = r.EmployeeId;
      END LOOP;
      DBMS_OUTPUT.PUT_LINE('Deleted '|| i ||' records from Employeetable'); 
      

      因为这会起作用,更重要的是,它更容易理解。由于代码的大小几乎从来都不是问题,因此保持代码简短和简略已经变得不那么重要了,但保持其易于理解非常重要,以便将来可以维护。

      【讨论】:

      • @TineO .. 非常感谢您的回复.. 但查询挂起,无法删除数据
      • @Tejash 是的,当涉及到大量数据时,性能可能很重要。但随着计算机能力的进步,性能优化变得不那么重要了。如果您知道自己正在处理大型数据集,那么您可能希望在工作时优化性能,但是尝试从一开始就优化所有代码以提高性能是一个坏主意,因为它很可能需要更长的时间并且可能可读性较差。而且性能优化甚至可能没有太大区别。
      • @Ravi 那么请在控制台中作为一个未命名的过程进行尝试。首先尝试使用 sql 查询来获取要删除的 ID,然后在简单的删除中使用其中的一个,如果这两个工作都尝试将其全部放入循环中,然后在其中添加您想要的任何其他内容。将其运行到最短的可重现示例,找出问题出现的确切位置,然后返回给我,我会尽力提供帮助。
      • 抱歉,我不同意这个切换到逐行删除的建议。如果删除大量行,这可能会导致巨大的性能问题。使用面向集合的 DELETE 或使用 PL/SQL 的 FORALL 语句来启用 D​​ELETE 的批量处理。
      • @TimeO,对于少量的行,确定 FORALL 是不必要的,但也不会担心单个面向集合的删除。最重要的是,Ravi 并没有真正给我们足够的信息来正确诊断和建议。
      猜你喜欢
      • 2020-05-21
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多