sql检查2列中的逻辑错误

发布于 2024-11-18 17:09:02 字数 323 浏览 2 评论 0原文

假设我有一个仅包含 2 列的 employee 表:

  • employee_id
  • manager_id

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

如果 AB 的管理器,我们如何强制执行检查,以便 A 的管理器可以采用除 B 之外的任何值,从而导致违反商业规则?

Assuming I have an employee table with 2 columns only:

  • employee_id
  • manager_id

All employees added to this table would have an accompanying manager_id that is actually an employee_id that already exists (save for one, the CEO probably doesn't have a manager, but that's not important).

If A is the manager of B, how do we enforce a check such that A's manager can take any value BUT B, thus resulting in a violation of the business rule?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

︶ ̄淡然 2024-11-25 17:09:02

我想说最好的方法是在插入表时创建一个触发器,该触发器将简单地检查manager_id NOT IN(从员工中选择employee_id,其中manager_id = %insertid%)

I'd say the best way would be to create a TRIGGER on the insert into the table that would simply check that manager_id NOT IN (SELECT employee_id from employee where manager_id = %insertid%).

我的黑色迷你裙 2024-11-25 17:09:02

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

另一半是检查约束,manager_id<>employee_id

Half of the answer is a foreign key: manager_id references employee(employee_id)

The other half is a check constraint, manager_id<>employee_id

若言繁花未落 2024-11-25 17:09:02

问题比这更深入,您希望避免图中出现任何循环,从而使其有效成为一

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

更新:但如果您更喜欢使用触发器来执行此操作,请查看公用表表达式 (CTE)。您可以在检查循环的触发器中创建递归查询:

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

The problem goes deeper than that, you want to avoid any cycles in your graph, making it effectively a tree.

I think you're better off doing that at the application level.

UPDATE: But if you prefer to do it with a trigger, take a look at common table expressions (CTEs). You can create a recursive query in a trigger that checks for cycles:

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

Note: it's assumed that employee_id is a primary key and manager_id is a foreign key pointing back to employee.employee_id.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文