Sql 使用触发器检查VARCHAR2是否只包含字母表

Sql 使用触发器检查VARCHAR2是否只包含字母表,sql,database,loops,plsql,triggers,Sql,Database,Loops,Plsql,Triggers,我需要写这样一个触发器来检查这个人的名字,如果这些人的名字中有数字,我会打印出他/她的id 我现在所拥有的: 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

我需要写这样一个触发器来检查这个人的名字,如果这些人的名字中有数字,我会打印出他/她的id

我现在所拥有的:

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;
/
它编译,当我试图触发这个触发器时,它什么也不做


我将非常感谢您的帮助。

使用正则表达式获得您的结果

在您的例子中,如果在n中得到一个数字,那么应该执行if子句

所以

似乎您也在尝试对digit使用正则表达式。但是,您的代码搜索的是包含[0-9]的字符串。就像蝙蝠[0-9]人,这不是你想要的结果

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

您可以分析以下查询,以便更好地了解此处发生的情况:

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

这不是你写触发器的方式

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

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;
/ 

使用正则表达式获得结果

在您的例子中,如果在n中得到一个数字,那么应该执行if子句

所以

似乎您也在尝试对digit使用正则表达式。但是,您的代码搜索的是包含[0-9]的字符串。就像蝙蝠[0-9]人,这不是你想要的结果

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

您可以分析以下查询,以便更好地了解此处发生的情况:

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

这不是你写触发器的方式

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

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;
/ 
这是一份像REGEXP_一样的工作!“\d”的正则表达式与一个数字匹配

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>
如果你的目标是在进入时去掉数字,但要小心,一家公司真的可以在名称中有一个数字,如Level3 Communications或3Com,如果是一个人,可能性较小,但现在谁知道呢!这是未经测试的:

CREATE OR REPLACE TRIGGER customer_bu
BEFORE INSERT OR UPDATE
ON customer
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
  -- If the new name contains a digit, strip it.
  if regexp_like(:new.name, '\d') then
    :new.name := regexp_replace(:new.name, '\d', NULL);
  end if;

END customer_bu;
/
这是一份像REGEXP_一样的工作!“\d”的正则表达式与一个数字匹配

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>
如果你的目标是在进入时去掉数字,但要小心,一家公司真的可以在名称中有一个数字,如Level3 Communications或3Com,如果是一个人,可能性较小,但现在谁知道呢!这是未经测试的:

CREATE OR REPLACE TRIGGER customer_bu
BEFORE INSERT OR UPDATE
ON customer
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
  -- If the new name contains a digit, strip it.
  if regexp_like(:new.name, '\d') then
    :new.name := regexp_replace(:new.name, '\d', NULL);
  end if;

END customer_bu;
/

您的代码中有几个问题:

在触发器中使用dbms_输出实际上没有意义;通常,插入将由不处理控制台输出的客户端代码执行。 明智的做法是提出一个例外。 您不需要在触发器代码中执行SELECT。事实上,这样做通常是多余的,或者会引起一个变异表错误。而是使用:new和:old来引用插入的行的值 在insert触发器之前在UPDATE之前对其进行次要命名有点混乱 使用正则表达式认真测试此业务规则;正则表达式是这类事情的规则 总之,这是未经测试的固定版本,我目前没有可供测试的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;

您的代码中有几个问题:

在触发器中使用dbms_输出实际上没有意义;通常,插入将由不处理控制台输出的客户端代码执行。 明智的做法是提出一个例外。 您不需要在触发器代码中执行SELECT。事实上,这样做通常是多余的,或者会引起一个变异表错误。而是使用:new和:old来引用插入的行的值 在insert触发器之前在UPDATE之前对其进行次要命名有点混乱 使用正则表达式认真测试此业务规则;正则表达式是这类事情的规则 总之,这是未经测试的固定版本,我目前没有可供测试的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;

不幸的是,这不起作用,但现在我有一个想法,我应该使用什么。谢谢lot@Yun8483,我的样本案例就是这样。好的,继续你的尝试:-我所做的调整会捕获像蝙蝠侠、蝙蝠侠1等的东西。是的,它工作得很完美,但我应该设法在循环中完成这项任务。虽然看起来这是不可能的,因为在循环中,我有表的变异幸运的是,这不起作用,但现在我知道应该用什么了。谢谢lot@Yun8483,我的样本案例就是这样。好的,继续你的尝试:-我所做的调整将捕捉像蝙蝠侠,蝙蝠侠1等的东西。是的,它工作完美,但我支持
ed设法在循环中执行此任务。虽然看起来这是不可能的,因为在循环中,我有表的变异C@I_am_Batman啊!多么愚蠢的错误,谢谢你指出这一点。修正了。我不小心在更新之前命名了这个触发器,我可能在更新触发器之前就想了一个问题,在做这个时,我忘了更改名称。我很抱歉。我应该用一个环。是的,我使用select进行了变异,但我需要以某种方式修复它。但是你的建议真的很有用。非常感谢。@我是蝙蝠侠!多么愚蠢的错误,谢谢你指出这一点。修正了。我不小心在更新之前命名了这个触发器,我可能在更新触发器之前就想了一个问题,在做这个时,我忘了更改名称。我很抱歉。我应该用一个环。是的,我使用select进行了变异,但我需要以某种方式修复它。但是你的建议真的很有用。非常感谢。我不知道为什么,但在我的情况下,它正好相反。我想那是因为我的代码。我将尝试修复并实现此方法。非常感谢。哦,你想在名字里写数字吗?我可能会把它颠倒过来。我不知道为什么,但在我的情况下,它正好相反。我想那是因为我的代码。我将尝试修复并实现此方法。非常感谢。哦,你想在名字里写数字吗?我可以把它倒过来。