我正在使用表格在数据库级别编写数据验证。
以下是我用于验证的表格结构:(理解记录有限)
SRNO | COL_NAME | OBJ_NAME | IS_MANDATORY | ALTER_COL | ERROR_MSG
1 | TITLE | Customer | Y | | Enter first name!
2 | FNAME | Customer | Y | LNAME | Either first or last name are required!
3 | MNAME | Customer | N | |
4 | LNAME | Customer | Y | FNAME | Either first or last name are required!
我已经编写了触发器,在根据validation
表将数据插入数据库之前对其进行验证:
CREATE OR REPLACE TRIGGER VALIDATE_CUST
BEFORE INSERT ON CUSTOMER REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW
DECLARE
T_COL_VAL NUMBER(4);
BEGIN
IF INSERTING THEN
FOR C IN
(select COL_NAME,ERROR_MSG from VALIDATE_COLS where IS_MANDATORY='Y' and OBJ_NAME='Customer' order by SRNO)
LOOP
T_COL_VAL := CASE C.COL_NAME
WHEN 'TITLE' THEN nvl(length(:NEW.TITLE),0)
WHEN 'FNAME' THEN nvl(length(:NEW.FNAME),0)
WHEN 'MNAME' THEN nvl(length(:NEW.MNAME),0)
WHEN 'LNAME' THEN nvl(length(:NEW.LNAME),0)
ELSE length('OK')
END;
IF T_COL_VAL=0 THEN
RAISE_APPLICATION_ERROR(-20001,C.ERROR_MSG);
END IF;
END LOOP;
END IF;
END;
以上触发器检查所有强制字段是否具有值。以上触发工作正常。
现在我想使用ALTER_COL
表中的validations
列。如果原始列为null,将检查ALTER_COL
列。例如,FNAME
或LNAME
都是强制性的。因此,如果未提供FNAME
,则触发器必须在引发错误之前检查LNAME
,并且仅当LNAME
也为空时才会引发错误。
我的问题是,我需要在if条件下重写case语句以获得ALTER_COL
的长度,如:
IF T_COL_VAL=0 THEN
--if `ALTER_COL` is not null
--Write case statement again to get the length of `ALTER_COL`
--If length of `ALTER_COL` is 0 then only raise following error
RAISE_APPLICATION_ERROR(-20001,C.ERROR_MSG);
END IF;
或者有更好的方法吗?
任何建议都将不胜感激!
Update1 (在@Wernfried回答之后)
我尝试编写可以避免重写代码的函数,但是我无法将NEW
传递给函数。我试过的功能看起来像。
CREATE FUNCTION FN_VALIDATE_CUST(COL_NAME in VARCHAR) return NUMBER as
BEGIN
return CASE COL_NAME
WHEN 'FNAME' THEN nvl(length(:NEW.FNAME),0)
WHEN 'MNAME' THEN nvl(length(:NEW.MNAME),0)
WHEN 'LNAME' THEN nvl(length(:NEW.LNAME),0)
WHEN 'TITLE' THEN nvl(length(:NEW.TITLE),0)
ELSE length('OK')
END;
END;
我无法将NEW
对象传递给上面的函数来访问列值。因此,如果我使用函数,我将需要在触发事件中编写case语句。
答案 0 :(得分:3)
或者有更好的方法吗?
当然 - 在数据库中使用NOT NULL和CHECK约束来执行此操作。这就是他们的目标,他们比你的方法更高效,更可靠,更灵活。
如果确实需要为违反约束提供自定义错误消息,请确保命名约束,并提供违反约束时要使用的自定义消息表。
编辑...
如果约束的强制取决于另一个表中是否存在客户编号,那么我宁愿在表中有一个标志,指示是否应用检查而不是空约束,并将其包含在约束定义。
例如:
... add constraint lname_required check (apply_constraints = 0 or lname is not null)
我不认为在这种情况下你可以避免需要触发器,因为你必须根据另一个表中客户编号的存在将“apply_constraints”的值保持为1(确保该表上的删除或插入更新此表中的相关值。
答案 1 :(得分:1)
您可以编写程序并在触发器中调用此过程。