2011-04-18 56 views
3

“存储过程通常用于数据验证或 封装组合若干SQL查询大型,复杂的处理指令。”sql:如何通过存储过程完成数据验证?

说这个Oracle reference。那么有人可以帮助我理解存储过程如何用于数据验证?因为将数据传递到存储过程中,它的经由其被明确设置为Oracle数据类型(或用户定义的类型,其也基于Oracle数据类型)参数进行发生

+0

好吧,我当然不是专家,这就是为什么我宁愿留下评论。是不是真的,你可以在存储过程中编写你的业务逻辑作为你的表的主要访问点,通过这个你可以在实际持久化之前验证数据? – 2011-04-18 05:47:34

回答

3

数据验证。只发生数据类型验证 - 必要时可以构建更深入的验证(IE:检查NUMBER数据类型中的小数)。参数化查询通常对于SQL注入来说更安全,但它确实取决于参数是什么以及查询的内容。

CREATE OR REPLACE PROCEDURE example (IN_VALUE NUMBER) IS 

BEGIN 

    SELECT t.* 
    FROM TABLE t 
    WHERE t.column = IN_VALUE; 

END; 

在这个例子中,提交VARCHAR /字符串将导致错误 - 比将导致一个错误编号支持其他任何东西。如果IN_VALUE数据类型不能隐式转换为TABLE.column的数据类型,你会得到一个错误。

存储过程封装了一个交易,这是允许复杂的处理指令(意思是,一个以上的SQL查询)。事务处理(IE:必须明确指定“COMMIT”或“ROLLBACK”)取决于设置。

+0

我在等你的答案;) – SuperMan 2011-04-18 06:04:13

+0

这意味着除了客户端验证之外,数据验证是通过存储过程在数据库级完成的。我们是否需要在两个层次都进行验证? – SuperMan 2011-04-18 06:08:20

+4

@SuperMan:是的,在两个层次都有效。始终在数据库上进行验证,就好像没有客户端验证一样。 – 2011-04-18 06:10:20

4

验证可能意味着一些东西,可以以各种方式的数据库中进行:

  • 列数据类型本身验证的一种形式:NUMBER列只接受有效号码等
  • 主键,唯一性和外键约束执行验证
  • CHECK约束执行其他简单的一排验证,如:
    • END_DATE> START_DATE
    • SALARY> 0
    • JOB =售货员或佣金IS NULL

然而,存在不能由任何上述的强制执行更复杂的验证规则,例如: - SALARY < = (SELECT max_sal FROM config_table) - emp.start_date BETWEEN start_date和它们被分配到

部门END_DATE

有各种各样的方式执行这些规则,包括数据库触发器,但经常优选的方法是创建一个存储PR流程,通常称为“API”以执行验证和动作,例如

PROCEDURE insert_emp (...) IS 
    ... 
BEGIN 
    -- Validate 
    -- 1) Salary less than max 
    SELECT max_sal 
    INTO l_max_sal 
    FROM config; 
    IF p_sal > l_max_sal THEN 
     error_pkg.raise_error ('Salary is too high'); 
    END IF; 
    ... 
    -- Insert 
    INSERT INTO emp (...) VALUES (...); 
END; 

然后,应用程序可以调用此过程,而不是直接执行更新,并且将执行所有必要的验证。事实上,应用程序可能会调用此过程 - 直接插入到表中可能会被禁用。

3

在一个理想的世界中,您选择的DBMS将是关系完整的,允许您编写任意复杂度的约束并支持多个赋值,以便您的数据库随时更新(即不需要推迟或禁用约束)声明。在现实世界中,我们拥有SQL。

理想的SQL的产品将是完整的SQL-92标准兼容:支持CREATE ASSERTION(架构级约束),允许在CHECK约束子查询,并支持事务中的约束的管理延迟,使您的数据库没有禁用的约束进行更新。可悲的是,甲骨文还没有达到这个水平的功能。因此,在现实世界中,我们必须诉诸程序代码来“管理”更新,同时保持数据的完整性。

例如,考虑一个真实的一对一的关系,是普通不过,随着业务规则如下:

数据库包含三个 relvars的 员工和项目的详细信息:EMP,PROJ和EMP_PROJ。每个 项目必须至少有一个 雇员,每个项目附件 必须参考现有项目。 当创建一个项目时,至少有一个员工必须同时连接 。

在Oracle中,你不能写一个ASSERTIONCHECK执行台间的限制,所以推迟约束的能力是无关紧要的在这种情况下。

一种方法可以编写具有适当参数的PROCEDURE以创建项目并将一个员工分配给项目。这样的程序将按照以下顺序(伪代码):

1)开始交易;

2)插入PROJ;

3)插入EMP_PROJ;

4)测试不符合名义约束条件的数据

EXISTS (
     SELECT * 
      FROM PROJ 
     WHERE NOT EXISTS (
          SELECT * 
          FROM EMP_PROJ 
          WHERE EMP_PROJ.project_code = PROJ.project_code 
         ) 
     ); 

5)如果测试发现非法数据,则回滚否则提交事务。

如果约束咬那么事务回滚和数据的完整性一直维持(尽管你也许会想处理更优雅此类验证失败:)

类似的程序将需要删除的员工从项目中防止将最后剩余分配的员工从项目中移除时的情形(应该防止员工搬迁还是应该删除项目?请问您的设计师:)

由于数据完整性只能由执行这样的程序代码,每个人都可以方便地将它封装在数据库中的一个PROCEDURE对象中n向用户授予对PROCEDURE的'执行'权限(而不是授予对基础表的增强权限)。强制一组用户(例如,最终用户应用程序)只能使用PROCEDURE来更新数据,因此应撤销其在基础表上的更新权限。这可能需要进一步的“辅助”功能,例如,将员工分配到项目并删除项目。如果你购买了“通过存储特效库访问所有数据库”学派,那么无论如何你都会这样做。

+1

+1,即使步骤1和5不属于存储过程,但在呼叫环境中,在我看来。 – 2011-04-19 10:44:30