【问题标题】:SQL Enforcing a constraint that requires some logicSQL 强制执行需要一些逻辑的约束
【发布时间】:2017-08-25 01:01:40
【问题描述】:

我不确定如何将问题表述得足够好,以便 Google 提供帮助 - 大多数结果都是关于指定外键以便您可以使用 JOIN 运算符。

编辑: 为了澄清,我在这里有两个主要概念 - 跟踪器和跟踪器读数​​。跟踪器可以有任意数量的输入。跟踪器的读数在该特定时间点具有跟踪器上每个输入的值

Tracker
  Id
  Name
  Inputs (List)
    Name

Reading
  Id
  TrackerId
  DateRecorded
  Some other properties
  Inputs (List)
    Value

我用以下结构对此进行了建模:

Tracker
  Id              (Key)
  Name

TrackerInput
  TrackerId       (Key 0, Foreign key)
  Index           (Key 1)
  Name

Reading
  Id              (Key)
  TrackerId       (Foreign key)
  DateRecorded
  Some other properties

ReadingInput
  ReadingId       (Key 0, Foreign key)
  Index           (Key 1)
  Value

如何通过 SQL 强制执行以下约束:

读数必须包含它所引用的跟踪器上每个输入的值。

【问题讨论】:

  • 你可以通过触发器强制执行
  • FK 是指表中某些列的值也必须是某些其他特定列和表的值。您对“FK”的使用没有意义。 (特别是“复合外键,目前分为两个表”。)你能在不使用它的情况下说出你想要的吗?在代码中,请说出一个表中的哪些列列表引用了另一个表中的哪些列列表。另外“输入”是什么意思? ...输入表的行? PS 您不需要 PK、FK 或任何其他约束来持有或声明即可加入。
  • 表的 CK 是一个唯一列集,其中不包含更小的唯一列集。给表 t 中的 FK(外键)“(c,...) 引用 u (d,...)”,其中 {d,...} 是 u 的 CK,如果 t 的行具有值 v,... 列 c,... 然后 u 的某些行具有值 v,... 列 d,.... 对于每个表,给出其 CK 和 FK。
  • 不幸的是,您的编辑没有澄清。请给出设计 1 和 2 的有效和几乎有效数据示例。请确认或更正:“如果 (i,t,...,v_1,...,v_x)) 在 Reading1 中,则某行 (t, n,(n_1,...,n_x)) 在 Tracker1 中”。 2张桌子还有什么总是正确的?此外,给定设计 1 的值,设计 2 中的值是多少,反之亦然?你的意思是,“(t,n,(n_1,...,n_x)) 是在 Tracker1 中,如果 & 仅当 (t,n) 在 Tracker2 中并且 (t,1,n_1),...,(t ,x,n_x) 是否在 TrackerInput 中?阅读同样如此? (设计 2 的约束似乎是一种关系划分变体。)
  • 换句话说:你的意思是select index from Reading r join Tracker t on r.trackerId = t.Id where length(r.inputs) <> length(t.inputs)是空的吗?即select 1 from Reading2 r join ReadingInput ri on r.id = ri.readingId group by ri.trackerId having count(*) <> (select count(*) from TrackerInput where t.trackerId = ri.trackerId) 是空的? PS请阅读并采取行动minimal reproducible example

标签: sql foreign-keys azure-sql-database composite-key


【解决方案1】:

读取中的输入必须引用跟踪器上的输入,但它需要一个复合外键,该外键目前分为两个表。如果我要强制执行外键约束,则必须将它们连接起来:

SELECT TrackerId, Index -- This is the foreign key I would like to enforce
FROM Readings
JOIN ReadingInputs ON ReadingId = Id

我猜到您的问题的那个版本意味着您希望强制 ReadingReadingInput 受制于它们的联接(因此该视图/查询)满足约束 foreign key (TrackerId, Index) references TrackerInput (TrackerId, Index)

您可以通过将Index 添加到Reading 以声明方式执行此操作,删除当前的ReadingReadingInput FK 并添加FK

(TrackerId, Index) references TrackerInput (TrackerId, Index) -- Reading
(ReadingId, Index) references Reading (Id, Index) -- ReadingInput

否则,您可以使用触发器。

【讨论】:

  • 我无法合并 ReadingReadingInput - 我更新了问题以进一步解释这种关系。我以前从未使用过触发器,你能举一个通过触发器强制执行此操作的简单示例吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
  • 2015-06-09
相关资源
最近更新 更多