【问题标题】:sql check for logical errors in 2 columnssql检查2列中的逻辑错误
【发布时间】:2011-09-29 00:01:57
【问题描述】:

假设我有一个只有 2 列的 employee 表:

  • employee_id
  • manager_id

添加到此表的所有员工都会有一个随附的 manager_id,它实际上是一个已经存在的 employee_id(除了一个,CEO 可能没有经理,但这并不重要)。

如果AB 的经理,我们如何强制检查A 的经理可以取除B 之外的任何值,从而导致违反业务规则?

【问题讨论】:

  • 您想在插入时检查条件还是对表本身施加限制??
  • 你不是在最后一段搞混了吗?
  • 您使用的是 MySQL、SQL Server 还是 Oracle?还是您真的在寻找适用于所有三个平台的编码解决方案?
  • 巴拉尼瓦什:插入时检查条件是否足够好
  • @Aaron Bertrand:我正在使用 sql server 2008。任何这些语言的解决方案都可以。我只需要知道它是如何在数据库级别完成的。

标签: sql sql-server sql-server-2008 database-design data-modeling


【解决方案1】:

我想说最好的方法是在插入表时创建一个 TRIGGER,它只会检查 manager_id NOT IN (SELECT employee_id from employee where manager_id = %insertid%)

【讨论】:

  • 那个触发器不能解决问题。它只检查自循环
  • @Downvoter:如果你投了反对票,因为你期待一个功能齐全的答案,或者报复别人的反对票——也许是时候长大了?
  • 我在接受答案之前尝试过投票,但它是注册用户,所以......接受了答案。
  • ... 并且 ON INSERT 触发器不需要检查这一点。由于员工是全新的,任何其他员工都可以成为他的经理
  • -1 不是因为我期待一个功能齐全的答案,而是至少一个指向正确方向的答案......
【解决方案2】:

一半的答案是外键:manager_id references employee(employee_id)

另一半是检查约束,manager_idemployee_id

【讨论】:

  • 哦,对,这不能确保树的事情。为此,特别是如果您打算对子层次结构进行操作,请查看嵌套集模型:en.wikipedia.org/wiki/Nested_set_model
  • 检查约束不能提供这个——触发器是唯一的选择
【解决方案3】:

问题远不止于此,您希望在 graph 中避免任何 循环,使其有效地成为一棵

我认为你最好在应用程序级别这样做。

更新:但如果您更喜欢使用触发器,请查看common table expressions (CTEs)。您可以在检查循环的触发器中创建递归查询:

create trigger prevent_management_cycles on employee
instead of update
as

declare @found_rows int

;with cycle_detector (employee_id) as (
  select employee_id from inserted
  union all
  select employee.employee_id from employee
  join cycle_detector 
  on employee.manager_id = cycle_detector.employee_id
) 
select @found_rows = count(*)
from cycle_detector
join inserted 
on inserted.manager_id = cycle_detector.employee_id

if @found_rows > 0
  raiserror('cycle detected!', 1, 1)
else
  -- carry on original update
  update employee 
    set employee.manager_id = inserted.manager_id
    -- other columns...
  from employee 
  join inserted on employee.employee_id = inserted.employee_id

注意:假设employee_id是主键,manager_id是指向employee.employee_id的外键。

【讨论】:

  • trigger 可以轻松解决问题。
  • 是的。但我通常更喜欢将这种 business 逻辑与应用程序的持久性机制分开。这种方式更易于维护、测试和发展。
  • 数据库构建基于业务实体及其规则。它也是集中的,同样易于维护,并且比除了最简单的应用程序之外的所有应用程序都更好地扩展负载。坦率地说,使用数据库作为“哑存储”完全是浪费......
  • 尽可能少的触发器。否则——主要是表和外键。 sprocs 的操作是我的首选,因为 ORM 受复杂查询的影响,而应用层中的 SQL 更多地涉及测试。并强制参数化...
  • @jaane:SO 答案不需要提供功能齐全的答案——这仅符合我们的最大利益。我相信你自己有能力,但你可以要求保罗澄清......
猜你喜欢
  • 2020-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-25
  • 1970-01-01
相关资源
最近更新 更多