PL/SQL 中的验证检查
Posted
技术标签:
【中文标题】PL/SQL 中的验证检查【英文标题】:Validation checks in PL/SQL 【发布时间】:2021-12-30 00:23:23 【问题描述】:根据我的项目要求,我需要将所有验证检查查询存储在一个表中,并验证另一个表的所有记录,并使用其验证状态更新每条记录。
例如,我有两个表名为 EMP
和 VALIDATIONS
验证表有如下两列:
------------------- --------------
Validation_desc Validation_sql
------------------ --------------
EID_IS_NULL related SQL should be here
SAL_HIGH related SQL should be here
EMP
table 有像eid,ename,sal,dept,is_valid,val_desc
这样的普通列。
我应该编写 PL/SQL 代码,该代码将从 VALIDATIONS
表中获取所有验证 sql,并检查 EMP
表的每条记录并验证它们。如果第一条记录通过VALIDATIONS
表中可用的所有验证成功,则EMP
表IS_VALID
列应更新为1,Validation_desc
对于该特定记录应为空。如果第二条记录通过 2 次检查失败,则该记录的 IS_VALID
列应更新为 0,Validation_desc
应更新为 Validation_desc
并以逗号分隔,同样,它应该检查 EMP
的所有记录的所有验证表。
我已尝试使用以下代码从两个表中获取所有详细信息,但无法编写验证逻辑。
CREATE PROCEDURE P_VALIDATION
as
TYPE REC_TYPE IS RECORD( Validation_desc VARCHAR2(4000),
Validation_sql VARCHAR2(4000));
TYPE VAL_CHECK_TYPE IS TABLE OF REC_TYPE;
LV_VAL_CHECK VAL_CHECK_TYPE;
CURSOR CUR_FEED_DATA IS SELECT * FROM EMP;
LV_FEED_DATA EMP%ROWTYPE;
BEGIN
SELECT Validation_desc, Validation_sql
BULK COLLECT INTO LV_VAL_CHECK FROM VALIDATIONS;
OPEN CUR_FEED_DATA;
LOOP
FETCH CUR_FEED_DATA INTO LV_FEED_DATA;
EXIT WHEN CUR_FEED_DATA%NOTFOUND;
FOR I IN LV_VAL_CHECK.FIRST .. LV_VAL_CHECK.LAST LOOP
----SOME VALIDATIONS LOGIC HERE--
END LOOP;
END LOOP;
CLOSE CUR_FEED_DATA;
END;
【问题讨论】:
【参考方案1】:没有单一类型的验证。验证可以是 null、不为 null、是真/假、返回行/无行等。有几种方法可以解决这个问题
编写您自己的断言包,其中包含用于每种验证类型的过程。在您的表中,您将存储验证类型和要评估的表达式。这是一项相当多的工作。 利用 utPLSQL 之类的开源测试框架并对其进行一些修改以满足您的需求。所有类型的验证都已经在那里实施。如果您决定走这条路,请注意版本 2 和 3 之间存在重大差异【讨论】:
【参考方案2】:首先要注意@KoenLostrie 的开场白:没有单一类型的验证。 这基本上是说没有单一的过程可以解决问题。但是使用数据库的内置验证应该是您的第一道攻击线。使用简单的预定义约束,这两个示例验证都不再是必需的:
使用约束来定义……——一个规则 限制数据库中的值。 Oracle 数据库允许您创建 六种类型的约束...
对于您概述的表格,约束可以处理您概述的验证和一些附加功能:
+-------------+--------+----------------------------------+-----------------------------------------------------+
| Validation | Column | Constraint Type | Description |
+-------------+--------+----------------------------------+-----------------------------------------------------+
| Eid_is_Null | eid | Primary Key | Guarantees eid is not null and is unique in table |
+-------------+--------+----------------------------------+-----------------------------------------------------+
| Sal_High | salary | Check (salary <= 50000) | Guarantees salary column is not greater than 50,000 |
+-------------+--------+----------------------------------+-----------------------------------------------------+
| Dept_OK | dept | not null | Ensures column is present |
+ +----------------------------------+-----------------------------------------------------+
| | | Foreign key to Departments table | Guarantees value exists in reference table |
+-------------+--------+----------------------------------+-----------------------------------------------------+
| Name_Ok | ename | not null | Ensures column is present |
+-------------+--------+----------------------------------+-----------------------------------------------------+
对于上面列出的以及添加的任何其他约束,您不需要需要查询来验证 - 数据库管理器根本不允许存在无效行。当然,现在您的代码需要处理产生的异常。 不幸的是,约束不能处理每个验证,因此您仍然需要验证例程来记录这些。但是,您不应该创建一个逗号分隔的列表(它们不仅违反了第一范式,而且它们总是比它们的价值更麻烦 - 当错误解决后如何更新列表?)而是创建一个新表 - @987654323 @如:
create table emp_violations (
emp_vio_id integer generated always as identity
, emp_id integer -- or type of emp_id
, vol_id integer -- or type of vio_id (the pk of violations table)
, date_created date
, date_resolved date
, constraint emp_violations_pk
primary key (emp_violation_id)
, constraint emp_violations_2_emp_fk
foreign key (emp_id)
references emp(mp_id)
, constraint emp_violations_2_violations_fk
foreign key (vio_id)
references violations(vio_id)
);
通过此功能,您可以轻松查看已经存在或当前存在哪些非约束违规行为,以及解决它们的时间。同时删除列Validation_desc
(不再需要)和is_valid
(可从未解决的emp_violations 导出,无需额外的列维护)。
如果您绝对必须获取 is_valid 和逗号分隔的违规列表,则使用 LISTAGG 函数创建一个视图。
【讨论】:
以上是关于PL/SQL 中的验证检查的主要内容,如果未能解决你的问题,请参考以下文章