【问题标题】:Conditional SQLite check constraint?条件 SQLite 检查约束?
【发布时间】:2010-04-10 23:48:34
【问题描述】:

我有一个由以下 SQL 定义的表:

CREATE TABLE test (
  id       integer PRIMARY KEY NOT NULL UNIQUE,
  status   text NOT NULL,
  enddate  date,
  /* Checks */
  CHECK (status IN ("Current", "Complete"))
);

我想添加一个约束,要求 enddate 为非空如果 status 为“完成”。

这可能吗?我正在使用 SQLite v3.6.16。

【问题讨论】:

    标签: sql sqlite constraints


    【解决方案1】:

    怎么样:

    CHECK (status = "Current" or (status = "Complete" and enddate is not null))
    

    【讨论】:

    • 谢谢,这行得通。这是唯一的方法吗?将来我可能会有更多的状态,并且支票可能会变得非常大。
    • 当约束变得非常复杂时,方法通常是在表格前面放置一个层来强制它。类似于存储过程层或数据访问库。
    • 好吧,SQLite 目前不支持存储过程,因此实现它的唯一方法是使用触发器或从 UI 层实现逻辑。
    • @Rezzie 我认为如果状态增长,你仍然可以使用这个结构稍加修改:CHECK (status <> "Complete" or (status = "Complete" and enddate is not null));请注意,它根本没有提到"Current"。您还需要保留 CHECK (status IN ("Current", "Complete")) 以验证可能的 status 值。如果多个状态需要enddate,您应该能够将<>= 更改为NOT ININ
    • 这个真的可以简写成(status <> "Complete" or enddate is not null)status的值不用重新检查,如果你检查or语句的后半部分,你已经知道status = "complete"
    【解决方案2】:
    CREATE TABLE test (
      id       integer PRIMARY KEY,
      status   text NOT NULL CHECK (status IN ('Current', 'Complete')),
      enddate  date NOT NULL
    );
    

    这将在 SQLite 中工作,CHECK 约束是内联编写的。我将双引号更改为撇号,以便可以在 PHP 中使用。

    【讨论】:

    • 你读过这个问题吗?他甚至把重要的部分用粗体你刚刚忽略的部分。
    【解决方案3】:

    没有什么能阻止您在单个表上拥有多个 CHECK 约束。 IMO 最简单、最容易扩展的解决方案:

    CHECK (status IN ("Current", "Complete"))
    CHECK (status <> "Complete" OR enddate IS NOT NULL)
    

    这使用了 if A then B 在逻辑上等价于 either not A or B这一事实。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多