如何在plsql块中执行删除语句并在过程中调用它

Posted

技术标签:

【中文标题】如何在plsql块中执行删除语句并在过程中调用它【英文标题】:how to execute delete statement inside plsql block and call it in a procedure 【发布时间】: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,告诉我们你得到了什么。 【参考方案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 并没有真正给我们足够的信息来正确诊断和建议。

以上是关于如何在plsql块中执行删除语句并在过程中调用它的主要内容,如果未能解决你的问题,请参考以下文章

如何使用plsql导出oracle数据建表语句,存储过程,视图.以及表中数据

plsql调用oracle存储过程有输入参数和输出参数 sql语句怎么写如题 谢谢了

如何在plsql中执行存储过程

我用plsql创建的存储过程为啥是无效的?

如何在plsql 执行导入导入语句: 在dos下能直接执行exp 和imp语句,但plsql下执行报错?

从用户那里获取 2 个输入并在 PLSQL 中调用过程