pl / sql中“where”条件的语句是什么

时间:2014-04-07 12:50:05

标签: sql oracle triggers sqlplus plsqldeveloper

我想在表客户端删除之前为每一行执行一个触发器,我试图做的是当有人试图删除一行时:

DELETE FROM Clients WHERE id=5 AND name = 'test';

我想在屏幕上打印一些内容,例如: "您在以下条件下删除:id为5,name为test" 或执行具有相同条件的另一个查询...

非常感谢任何帮助

编辑

我们假设用户输入了以下查询:DELETE FROM Clients where name = 'test'

create or replace 
TRIGGER DELETECLIENT 
BEFORE DELETE ON CLIENTS
DECLARE 
pragma autonomous_transaction;
name1 clients.name%Type; 
BEGIN
  select name into name1 from clients where  name = %I want here the name in the user query %;   
  IF name1 != null THEN 
    DELETE FROM clients WHERE name = name1;
    commit;
  END IF; 
END; 

我测试的内容:

我尝试添加:old.name和:new.name,但是当我的数据库中没有该行时,这不起作用

PS :我这样做只是出于教育目的,我知道脚本没有意义。我只是不知道如何实现以下任务:获取在查询中的WHERE之后键入的参数

1 个答案:

答案 0 :(得分:1)

correlation names and pseudorecords代表,默认情况下为:old:new,对行级触发器只有任何意义:

  

注意:
  本主题仅适用于在行级触发的触发器 - 即行级简单DML触发器和具有行级时间点部分的复合DML触发器。

您无法在语句级触发器中引用这些内容,只有:olddelete触发器中具有任何含义。另一方面,即使没有数据受到影响,语句级触发器也会触发,而在您的示例中,如果没有数据被删除,则行级触发器不会触发 - 因为表中没有匹配的行。 (这也适用于instead of视图触发器,以防您想知道这是否是一种解决方法。

所以基本上你不能做你正在尝试的事情 - 有条件地决定是否从另一个表中删除 - 来自触发器。触发器很少是正确的答案。对于你的情况,如果它在我的桌子上不存在,我应该尝试在其他网站上找到并删除它'你可以尝试在本地删除一行,测试它是否做了什么,然后决定从远程删除表,如果没有。在PL / SQL块中,可能很简单:

create procedure delete_client(p_name clients.name%type) as
begin
  delete from clients where name = p_name;
  if sql%rowcount = 0 then
    delete from clients@site2 where name = p_name;
  end if;
end delete_client;
/

而不是直接从表中删除,而是让每个人都调用该过程。假设您从一些数据开始:

select * from clients;

        ID NAME     
---------- ----------
         1 Joe        
         2 Anna       

select * from clients@site2;

        ID NAME     
---------- ----------
         1 Joe        
         3 Max        

然后调用两个名称的程序:

exec delete_client('Joe');
exec delete_client('Max');

...已适当删除了本地和远程记录:

select * from clients;

        ID NAME     
---------- ----------
         2 Anna       

select * from clients@site2;

        ID NAME     
---------- ----------
         1 Joe        

Joe仅从本地架构中删除,尽管两者都存在; Max在本地不存在,因此从远程模式中删除。

它不一定是程序;如果您正在通过JDBC等删除,您可以测试execute()调用的结果以查看受影响的行数,这是sql%rowcount正在做的所有行,并且应用程序代码可以决定是否做第二个delete

但是使用一个程序(可能在一个程序包中),您可以对其授予execute,并从用户中删除delete权限,这样他们就无法绕过此检查并直接执行{{ 1}}


如果确实想要一些“显示”输出用于测试目的:

delete from clients where ...

但是,您不应该假设任何调用您的程序的人都会create procedure delete_client(p_name clients.name%type) as begin delete from clients where name = p_name; if sql%rowcount > 0 then dbms_output.put_line('Deleted ' || sql%rowcount || ' rows from local schema for "' || p_name || '"'); else delete from clients@site2 where name = p_name; if sql%rowcount > 0 then dbms_output.put_line('Deleted ' || sql%rowcount || ' rows from remote schema for "' || p_name || '"'); else dbms_output.put_line('No rows deleted on local or remote schema for "' || p_name || '"'); end if; end if; end delete_client; / set serveroutput on exec delete_client('Joe'); anonymous block completed Deleted 1 rows from local schema for "Joe" exec delete_client('Max'); anonymous block completed Deleted 1 rows from remote schema for "Max" exec delete_client('Fred'); anonymous block completed No rows deleted on local or remote schema for "Fred" 开启,或者甚至使用能够使用serveroutput消息的客户端。