检查VARCHAR2是否仅包含使用触发器的字母表

时间:2016-06-09 19:25:14

标签: sql database loops plsql triggers

我需要编写一个触发器来检查此人的姓名,如果这些人的姓名中有任何数字,则会打印出他/她的身份证。

我现在拥有的东西:

set SERVEROUTPUT ON
create or replace trigger BeforeUpdate
Before insert on customer
for each row 

declare 
n varchar2(10);
counter number;
nextR number:=0;

begin
select count(id_customer) into counter from customer;

LOOP
nextR:= nextR +1;
select cname into n from customer where id_customer = nextR;
if n not like '%[0-9]%' then 
DBMS_OUTPUT.PUT_LINE(nextR || ' has incorrect name');
end if;
exit when nextR = counter;
end loop;
end;
/

它编译,当我试图触发此触发器时,它什么都不做。

我将不胜感激任何帮助。

3 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题:

  • 在触发器中使用dbms_output并不是真的有意义;通常,INSERT将由不处理控制台输出的客户端代码执行。 明智的做法是提出异常。
  • 您不需要在触发器代码中执行SELECT。实际上,这样做通常要么是多余的,要么引发变异表错误。相反,使用:new和:old来引用已插入行的值
  • (次要)命名前插入触发器BeforeUpdate有点令人困惑
  • 使用正则表达式来测试此业务规则(严重;正则规则适用于此类事情)

总而言之,这里是固定版本(未经测试,我现在没有可用于测试的Oracle实例):

create or replace trigger TR_BI_CUSTOMER
Before insert on customer
for each row 
begin
  if regexp_like(:new.name, '.*[0-9].*') then 
    raise_application_error(-20001, 'Incorrect name: ' || :new.name);
  end if;
end;

答案 1 :(得分:1)

使用正则表达式来获得结果。

在你的情况下,如果你在n中得到一个数字,你的if子句应该被执行。

所以,

if regexp_replace(n,'[^[:digit:]]') IS NOT NULL then      
DBMS_OUTPUT.PUT_LINE(nextR || ' has incorrect name');
end if

您似乎也在尝试使用正则表达式来表示数字。但是,您的代码搜索的是包含[0-9]的字符串。与Bat[0-9]Man一样,这不是您想要的结果。

在我的代码中,替换给定名称中的任何表达式都不是数字。如果名称不包含任何数字,则正则表达式将返回null。如果任何地方有任何数字,表达式将返回这些数字。

您可以分析以下查询,以便更好地掌握此处发生的事情:

select regexp_replace(cname,'[^[:digit:]]') OUTP, cname from customer;

编辑:

这不是你编写触发器的方式!

每次插入时都会触发触发器。你不需要柜台。您需要使用:新参考

set SERVEROUTPUT ON
create or replace trigger update or
Insert on customer
for each row 

begin
if regexp_replace(:NEW.cname,'[^[:digit:]]') IS NOT NULL then 
DBMS_OUTPUT.PUT_LINE(nextR || ' has incorrect name');
end if;
end;
/ 

答案 2 :(得分:1)

这是requests的工作! REGEXP_LIKE()的正则表达式匹配一个数字。

'\d'

如果你的目标是去掉路上的数字(但要小心,公司真的可以在Level3通信或3Com这个名称中有一个数字,如果它是一个人,它的可能性较小但是现在谁知道! )这是未经测试的:

SQL> with tbl(id, name) as (
      select 1, 'Batman'    from dual union
      select 2, 'Robin1'    from dual union
      select 3, 'Supe4rman' from dual union
      select 4, '3Joker'    from dual
    )
    select id, name bad_name
    from tbl
    where regexp_like(name, '\d');

        ID BAD_NAME
---------- ---------
         2 Robin1
         3 Supe4rman
         4 3Joker

SQL>