我有一张表T_USER
,如下所示:
CREATE TABLE T_USER (
ID_USER NUMBER(10) NOT NULL,
LASTNAME VARCHAR2(75 CHAR) NOT NULL,
FIRSTNAME VARCHAR2(75 CHAR) NOT NULL,
LOGIN VARCHAR2(75 CHAR) NOT NULL,
PASSWD VARCHAR2(168 BYTE) NOT NULL,
ACTIVE NUMBER(1) /* IF USER IS ACTIVE OR NOT */
);
ID_USER 是主键, LOGIN 是唯一的
我想在插入ACTIVE = 0
的用户时自动生成用户的登录信息。
登录名为名字的第一个字母,姓氏的5个首字母和[1-50]中的随机数。如果新用户没有名字,那就是公司,所以我们只从名字中取6个字母(+随机数)。
一些例子:
FIRSTNAME: Bruce, LASTNAME: Wayne
应生成LOGIN: bwayne13
FIRSTNAME: Peter, LASTNAME: Parker
应生成LOGIN: pparke45
FIRSTNAME: NULL, LASTNAME: Google Inc
应生成LOGIN: google6
我对SQL触发器很陌生,到目前为止我已经做了很多事情:
CREATE OR REPLACE TRIGGER GENERATE_LOGIN
BEFORE INSERT ON T_USER
FOR EACH ROW WHEN (ACTIVE = 0)
DECLARE
LOG T_USER.LOGIN%TYPE;
BEGIN
IF(:NEW.LOGIN IS NULL) THEN
IF(:NEW.FIRSTNAME IS NULL) THEN /* It's a company */
SELECT REPLACE(LOWER(REGEXP_REPLACE(:NEW.LASTNAME,'[^A-Z0-9]')),'ç','c') /* I remove non alphanumeric characters */
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
ELSE /* It is a real person */
SELECT SUBSTR(:NEW.FIRSTNAME, 1, 1) || SUBSTR(:NEW.LASTNAME, 1, 5)
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
END IF;
END IF;
:NEW.LOGIN := LOG;
END;
/
正如您猜测的那样,我的触发器不起作用(我有ORA-04076 error)。顺便说一下,我也不检查生成的登录是否是唯一的......
你可以帮帮我吗? :)答案 0 :(得分:1)
在FOR EACH ROW WHEN (ACTIVE = 0)
是触发器标头的一部分之前,我还没有看到这种语法。显然,这是错误的来源。删除它时,触发器成功编译。对我来说,它没有意义,因为编译器不知道你在这里引用的ACTIVE
是旧值还是新值。也许其他人可以进一步澄清这一部分。
无论如何,我可以用传统的IF语句替换它,并且触发器成功编译:
CREATE OR REPLACE TRIGGER GENERATE_LOGIN
BEFORE INSERT ON T_USER
FOR EACH ROW
DECLARE
LOG T_USER.LOGIN%TYPE;
BEGIN
IF (:NEW.ACTIVE = 0) THEN --replace WHEN (ACTIVE = 0)
IF(:NEW.LOGIN IS NULL) THEN
IF(:NEW.FIRSTNAME IS NULL) THEN /* It's a company */
SELECT REPLACE(LOWER(REGEXP_REPLACE(:NEW.LASTNAME,'[^A-Z0-9]')),'ç','c') /* I remove non alphanumeric characters */
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
ELSE /* It is a real person */
SELECT SUBSTR(:NEW.FIRSTNAME, 1, 1) || SUBSTR(:NEW.LASTNAME, 1, 5)
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
END IF;
END IF;
:NEW.LOGIN := LOG;
END IF;
END;
/
<强>更新强>
检查后,您可以使用此语法,NEW
关键字(不带冒号)。因此可以像这样重写相同的触发器:
CREATE OR REPLACE TRIGGER GENERATE_LOGIN
BEFORE INSERT ON T_USER
FOR EACH ROW WHEN (NEW.ACTIVE = 0) THEN
DECLARE
LOG T_USER.LOGIN%TYPE;
BEGIN
IF(:NEW.LOGIN IS NULL) THEN
IF(:NEW.FIRSTNAME IS NULL) THEN /* It's a company */
SELECT REPLACE(LOWER(REGEXP_REPLACE(:NEW.LASTNAME,'[^A-Z0-9]')),'ç','c') /* I remove non alphanumeric characters */
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
ELSE /* It is a real person */
SELECT SUBSTR(:NEW.FIRSTNAME, 1, 1) || SUBSTR(:NEW.LASTNAME, 1, 5)
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
END IF;
END IF;
:NEW.LOGIN := LOG;
END;
/
阅读here
答案 1 :(得分:1)
这是一项带有单一性检查的提案。
CREATE OR REPLACE TRIGGER GENERATE_LOGIN
BEFORE INSERT ON T_USER
FOR EACH ROW WHEN (new.ACTIVE = 0)
DECLARE
LOG T_USER.LOGIN%TYPE;
nlogin number(10); -- counter for the unicity
BEGIN
IF(:NEW.LOGIN IS NULL) THEN
loop
IF(:NEW.FIRSTNAME IS NULL) THEN /* It's a company */
SELECT REPLACE(LOWER(REGEXP_REPLACE(:NEW.LASTNAME,'[^A-Z0-9]')),'ç','c') /* I remove non alphanumeric characters */
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
ELSE /* It is a real person */
SELECT SUBSTR(:NEW.FIRSTNAME, 1, 1) || SUBSTR(:NEW.LASTNAME, 1, 5)
|| DBMS_RANDOM.VALUE(1,50) /* Concat random in [1-50] */
INTO LOG FROM DUAL;
END IF;
select count(login) into nlogin from t_user where login=log; -- checking
exit when nlogin=0; -- exiting the loop if none else have that login
end loop;
:NEW.LOGIN := LOG; -- moved this here, as it doesn't make sense after the end if, log has not been defined in that case
END IF;
END;
/