在将数据输入插入表之前,使用CHECK约束或使用if语句,哪种方式更好地验证数据输入?有更好的方法来验证它吗?
1)
DECLARE
INVALID_DATE EXCEPTION;
...
-- Check if date is valid
IF TO_DATE(dt,'DD/MM/YYYY') > TO_DATE('10/10/2010','DD/MM/YYYY')THEN
RAISE INVALID_DATE;
END IF;
-- Insert data only if it is valid
INSERT INTO Table VALUES(dt);
EXCEPTION
WHEN INVALID_DATE
THEN DBMS_OUTPUT.PUT_LINE('Date is not valid');
...
2)
...
-- Do NOT check if date is valid and let an
-- CHECK constraint exception(CH_TABLE1) be raised if it is invalid
INSERT INTO Table VALUES(dt);
EXCEPTION
WHEN CHECK_CONSTRAINT_VIOLATED THEN
IF SQLERRM LIKE 'ORA-02290:%CH_TABLE1%' THEN
DBMS_OUTPUT.PUT_LINE('Date is not valid');
...
END IF;
...
答案 0 :(得分:1)
如果更新/插入可能来自多个应用程序/脚本,尤其是即席查询,那么检查约束会将所需的业务逻辑放在一个位置,这是一件好事。
如果更新/插入来自一个应用程序/源,则可能最好在应用程序中进行检查(在本例中为存储过程)。
有一个检查约束是一个捕获所有,但它有点隐藏。
答案 1 :(得分:1)
这取决于 - 通常需要采用多层方法。
例如,您可能有一组简单的业务规则,可以作为检查约束直接在数据库中维护。我只将它们用于简单,独立的检查。
示例 - 检查Y / N标志:
alter table example_table add constraint ck_example_table_flag
check (flag is null or flag in ('Y', 'N');
在这种情况下,如果您在此列中获得任何其他值,则知道数据是错误的,并且这不是一个随时间变化的规则。添加此约束将阻止任何应用程序破坏您的数据。
对于可能不是自包含的更复杂的业务规则,例如,如果日期取决于输入值的人或另一个表中另一个字段的内容,那么我将在'应用'
有时候'应用程序' 是数据库 - 在这种情况下,您的检查约束可能在表触发器或处理所有表更新的打包pl / sql中。例如:
example_app.update_data(id => 1000, value => 'foo');
如果这是处理数据更新的方式,那么将业务规则作为检查约束,带检查的触发器或直接在update_data
过程中处理没有任何问题。
在许多企业环境中,应用程序层和数据库层将由不同的团队处理。如果您在支持应用程序层的团队中,您可能会发现为数据库团队提出更改请求以设置检查约束太麻烦了 - 在这种情况下,向应用程序层添加一些逻辑将感觉更直接。相反,数据库团队可能会发现它更直接。
@Bohemian makes an excellent point关于在有多个客户端时使用检查约束来强制执行数据完整性。
答案 2 :(得分:1)
支持使用检查约束的另一个考虑因素是它们可以通过允许优化器推断某些值不能出现在表中来提高性能。
存在限制日期列的约束以检查:
my_col>日期'2010-01-01'
...带有谓词的查询,例如:
my_col = date'2009-01-01'
...可以确定不会从该表返回任何行。