【问题标题】:Foreign key mismatch in SQLite3SQLite3 中的外键不匹配
【发布时间】:2018-07-17 14:10:24
【问题描述】:

我将 SQLite3 用于简单的应用程序(如议程)。议程是多语言的。这就是为什么我有更多语言的桌子的原因(语言的数量必须是独立的)

起初,我有一个表rooms,其定义如下:

CREATE TABLE rooms 
(
    room_code VARCHAR2(32),
    lang_code CHAR(2),
    room_name VARCHAR(32),
    PRIMARY KEY (room_code, lang_code),
    FOREIGN KEY (lang_code) REFERENCES languages (lang_code),
    CHECK (LENGTH(lang_code) = 2),
    CHECK (room_code <> '')
);

然后我有一个表 events 具有以下定义:

CREATE TABLE events 
(
    room_code VARCHAR2(32) NOT NULL,
    message_code VARCHAR(64) NOT NULL,
    time_start DATETIME NOT NULL ,
    time_end DATETIME NOT NULL,
    PRIMARY KEY (message_code, room_code),
    FOREIGN KEY (room_code) REFERENCES rooms (room_code),
    -- Check the time is between 00:00 and 23:59
    CHECK (time_start and time_end BETWEEN TIME('00:00') AND TIME('23:59')),
    -- Start time must be lower than end time
    CHECK (time_start < time_end),
    -- Message code cannot be empty
    CHECK (message_code <> '') 
);

但事实上,我在任何插入尝试中都遇到了这个错误:

Error: near line 91: foreign key mismatch - "events" referencing "rooms"

为什么我不能引用另一个表?我读到表 B 的所有外键都必须是表 A 中的 PRIMARY KEY。但是这种依赖对我来说是可以的。来自表 events 的外键 room_code 它也是表 rooms 中的主键 room_code

这可能不是 TRIGGERS 的解决方案吗?事实上,如果可能的话,我想使用 KEYS 而不是 TRIGGERS。谢谢

最好的问候

【问题讨论】:

    标签: sql sqlite foreign-keys primary-key


    【解决方案1】:

    我认为您的问题是由于不符合:-

    通常,外键约束的父键是主键 的父表。如果它们不是主键,则为父键 键列必须共同受 UNIQUE 约束或 有一个唯一的索引。如果父键列有唯一索引, 那么该索引必须使用在 父表的 CREATE TABLE 语句。例如,

    SQLite Foreign Key Support

    注意主键,而不是主键的一部分。

    简而言之,外键引用的列必须是唯一的。

    因此,您可以为 room_code 列添加索引或定义它以利用 UNIQUE 约束,例如:-

    DROP TABLE IF EXISTS events;
    DROP TABLE IF EXISTS rooms;
    DROP INDEX IF EXISTS room_code_idx;
    CREATE TABLE IF NOT EXISTS rooms (
        room_code VARCHAR2(32) UNIQUE, --<<<<<<<<<< ADDED UNIQUE
        lang_code CHAR(2),
        room_name VARCHAR(32),
        PRIMARY KEY (room_code, lang_code),
        -- FOREIGN KEY (lang_code) REFERENCES languages (lang_code)  
        CHECK (LENGTH(lang_code) = 2),
        CHECK (room_code <> '')
    );
    
    CREATE TABLE IF NOT EXISTS events (
        room_code VARCHAR2(32) NOT NULL,
        message_code VARCHAR(64) NOT NULL,
        time_start DATETIME NOT NULL ,
        time_end DATETIME NOT NULL,
        PRIMARY KEY (message_code, room_code),
        FOREIGN KEY (room_code) REFERENCES rooms (room_code),
        -- Check the time is between 00:00 and 23:59
        CHECK (time_start and time_end BETWEEN TIME('00:00') AND TIME('23:59')),
        -- Start time must be lower than end time
        CHECK (time_start < time_end),
        -- Message code cannot be empty
        CHECK (message_code <> '') 
    );
    
    INSERT INTO rooms VALUES('room001','xx','This is room 1');
    INSERT INTO events VALUES('room001','This is a message for room 1','01:00','02:00');
    
    • 为方便/简洁起见,注释掉 lang_code 的 FK

    结果:-

    INSERT INTO rooms VALUES('room001','xx','This is room 1')
    > Affected rows: 1
    > Time: 0.3s
    
    
    INSERT INTO events VALUES('room001','This is a message for room 1','01:00','02:00')
    > Affected rows: 1
    > Time: 0.301s
    

    当然,您可以将 PRIMARY KEY 定义为 room_code 列,因为它必须是唯一的。

    如果 room_code 列将/可能不是唯一的,并且唯一保证的唯一性将是 room_code 列和 lang_code 列的组合.您需要定义一个复合外键(请参阅上面的链接)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-28
      • 1970-01-01
      相关资源
      最近更新 更多