2016-06-09 41 views
1

我需要編寫這樣一個觸發器來檢查人員姓名,如果他們的姓名中有任何數字,將會打印出他/她的ID。檢查VARCHAR2是否僅包含使用觸發器的字母表

我有現在:

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

它編譯,當我試圖觸發此觸發它什麼也不做。

我將不勝感激任何幫助。

回答

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

不幸的是,這是行不通以及 但現在我h我想知道我應該使用什麼。 非常感謝 – Yun8483

+0

@ Yun8483,它的確適用於我的示例。好的,繼續嘗試:-)我所做的調整將捕獲像Bat9Man,Bat9Man1等等的東西。 –

+0

@ Yun8483,編輯 –

1

這是REGEXP_LIKE()的工作! '\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> 

如果你的目標是去掉在路上的數字(不過要小心,一個公司真正能有像第三級通訊公司或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; 
/
+0

我不是爲什麼,但在我的情況下,它反之亦然。我認爲這是因爲我的代碼。我會嘗試修復和實施這種方法。萬分感謝。 – Yun8483

+0

@ Yun8483 - 請參閱我的更新。 –

+0

哦,你想在名字中的數字?我可能會顛倒過來。 –

2

有一對夫婦的代碼中的問題:

  • 在觸發器使用dbms_output並沒有真正意義;通常,INSERT將由不處理控制檯輸出的客戶端代碼執行。 明智的是提出異常。
  • 您不需要在觸發代碼中執行SELECT。事實上,這樣做通常或者是多餘的,或者引起表格變異錯誤。相反,使用:新:舊指已插入
  • (未成年人)行的值命名之前,INSERT觸發器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; 
+0

@I_am_Batman Doh!多麼愚蠢的錯誤,謝謝你指出這一點。固定。 –

+0

我不小心將這個觸發器命名爲BeforeUpdate,在更新觸發器之前我可能正在考慮Abot,同時做這個事情並且畢竟忘了更改名稱。我很抱歉。 我本來應該使用一個循環。 是的,我有使用select的突變,但我需要以某種方式修復它。 但是你的建議真的很有幫助。萬分感謝。 – Yun8483

相關問題