【问题标题】:SQL constraint check if entry in another tableSQL 约束检查是否在另一个表中的条目
【发布时间】:2018-08-10 21:46:35
【问题描述】:

基于一个整数 ID,如何限制引用一个公共表的两个表包含另一个表中已经存在的相同元素?

创建个人信息的基本表:

CREATE TABLE person (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    info VARCHAR(10)
);

然后创建两个引用person 的表:

CREATE TABLE special (
    id INTEGER PRIMARY KEY,
    skill VARCHAR(10),
    FOREIGN KEY (id) REFERENCES person(id)
);

CREATE TABLE snowflake (
    id INTEGER PRIMARY KEY,
    meltingpoint DECIMAL,
    FOREIGN KEY (id) REFERENCES person(id)
);

但是,我想限制这两个表包含同一个人。

所以我认为这样可以解决问题,但 SQLite3 会出现语法错误(靠近 CHECK)。

ALTER TABLE special ADD CHECK (
    (SELECT COUNT(*) FROM snowflake WHERE snowflake.id = special.id) = 0
);

或基于this answer

ALTER TABLE special ADD CHECK (
    NOT EXISTS (SELECT 1 FROM snowflake WHERE snowflake.ID = special.ID)
);

如何实现?我是在做某事还是应该采取完全不同的方法?

【问题讨论】:

    标签: sql sqlite constraints


    【解决方案1】:

    您可以在 'person' 中有两个外键,分别指向 'special' 和 'snowflake',并检查其中只有一个键有值。另一种解决方案可能是将 'special' 和 'snowflake' 加入一个表中,并检查是否只给出了 'skill' 或 'meltingpoint' 之一。

    【讨论】:

    • 那么CHECK不能引用另一个表?
    【解决方案2】:

    您不能使用 ALTER TABLE 向列添加 CHECK

    您只能使用 ALTER TABLEADD 列,然后该列可以具有 CHECK 约束。 您不能重命名列,也不能删除列。

    最简单的方法是在创建表时在列中定义 CHECK。如果您有需要保留的数据,那么您必须:-

    • 1)创建一个新表,
    • 2) 将原表中的数据复制到新表中,
    • 3) 重命名/删除原始文件和
    • 4) 将新表重命名为原表的名称。

    【讨论】:

    • technet.microsoft.com/fi-fi/library/ms179491(v=sql.105).aspx 这里CHECK 是在创建表后添加的,这只是在SQLite中我不能这样做吗?
    • 另外,在创建表时我不能真正定义两者,因为两个引用表之一尚未创建。因此,必须在之后添加至少一个约束。
    • SQLite 的 ALTER 就像我回答的那样。见ALTER TABLE。但是,您还会看到,根据SQL Data ConstraintsCHECK 约束的表达式可能不包含子查询。
    【解决方案3】:

    documentation 说:

    CHECK 约束的表达式可能不包含子查询。

    所以你必须使用triggers:

    CREATE TRIGGER no_snowflake_if_special
    AFTER INSERT ON snowflake
    WHEN EXISTS (SELECT * FROM special WHERE id = NEW.id)
    BEGIN
        SELECT RAISE(FAIL, "a special with the same ID already exists");
    END;
    
    -- same for special
    

    【讨论】:

    • 谢谢!这是什么NEW?有必要吗(对比special.id = id)?它是插入元组的句柄吗(有人会这样认为..)?
    • 是的;请参阅链接文档。
    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 2020-12-03
    • 2011-01-28
    • 1970-01-01
    • 2011-05-22
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多