2016-06-09 1 views
1

Мне нужно написать такой триггер, который будет проверять имя человека и распечатать его/ее идентификатор, если у этих людей есть какие-либо цифры в их именах.Проверьте, содержит ли 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; 

EDIT:

Это не то, как вы пишете триггер!

Триггер будет запускаться каждый раз, когда будет вставлена ​​вставка. Вам не нужен счетчик. Вы должны использовать: NEW ссылки

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 ave идея того, что я должен использовать. Большое спасибо – 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> 

Если ваша цель состоит в том, чтобы вырезать цифры на пути в (но будьте осторожны, компания действительно может иметь номер в названии, как 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; 
/
+0

Не знаю почему, но в моем случае он работает точно наоборот. Я думаю, это из-за моего кода. Я попытаюсь исправить и реализовать этот метод. Большое спасибо. – Yun8483

+0

@ Yun8483 - см. Мое обновление. –

+0

О, ХОТИТЕ номера в именах? Я мог бы его отменить. –

2

Есть несколько проблем в вашем коде:

  • с использованием dbms_output в триггере на самом деле не имеет смысла; обычно INSERT будет выполняться клиентским кодом, который не обрабатывает вывод консоли. Разумным является вместо этого исключение.
  • Вам не нужно выполнять SELECT в коде запуска. Фактически, выполнение этого обычно будет либо лишним, либо повысит погрешность таблицы ошибок.Вместо этого используйте: новый и: старый, чтобы обратиться к значениям строки, которая была вставлена ​​
  • (несовершеннолетней) именование, прежде чем вставить триггер 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 До! Какая глупая ошибка, спасибо за это. Исправлена. –

+0

Я случайно назвал этот триггер BeforeUpdate, я, вероятно, думал об abot перед триггером обновления, делая это, и в конце концов забыл изменить имя. Я сожалею об этом. Я должен был использовать петлю. И да, у меня были мутации с помощью select, но мне нужно было как-то исправить это. Но ваши советы действительно полезны. Большое спасибо. – Yun8483

Смежные вопросы