代码之家  ›  专栏  ›  技术社区  ›  Alex B

`尽管使用了触发器,但复合主键上的唯一约束失败

  •  0
  • Alex B  · 技术社区  · 6 年前

    考虑到我们得到了一个 UNIQUE constraint failed 插入 表中的新行。

    该行由多个主键组成,这些主键被链接以创建 ,即由4个字段的组合组成 id , id_x id_y id_z .

    第一个 身份证件 钥匙必须是 unique 身份证号码 , 身份证号码 foreign keys .

    因为我们不能使用 a上的功能 复合键 在sqlite中,我们使用下面的触发器,在这里我们查找每个字段的最高整数并加1以满足 独特性 约束条件:

    CREATE TRIGGER [autoincrement]
             AFTER INSERT
                ON table_main
              WHEN NEW.id IS NULL
    BEGIN
        UPDATE table_main
            SET id = IFNULL((SELECT MAX(id) FROM table_main) + 1, 0),
            id_x = IFNULL((SELECT MAX(id_x) FROM table_main) + 1, 0),
            id_y = IFNULL((SELECT MAX(id_y) FROM table_main) + 1, 0),
            id_z = IFNULL((SELECT MAX(id_z) FROM table_main) + 1, 0);
    END; 
    

    尽管如此,我们仍然得到 错误。

    更新: 有一个 forign key 约束。

    2 回复  |  直到 6 年前
        1
  •  1
  •   MikeT    6 年前

    因为我们不能在复合键上使用自动递增功能

    下面有一个复合键,其唯一id递增(您称之为自动递增):-

    DROP TABLE IF EXISTS table_main;
    DROP TABLE IF EXISTS table_fkx;
    DROP TABLE IF EXISTS table_fky;
    DROP TABLE IF EXISTS table_fkz;
    DROP TRIGGER IF EXISTS [autoincrement];
    CREATE TABLE IF NOT EXISTS table_fkx (id INTEGER PRIMARY KEY, datacol TEXT);
    CREATE TABLE IF NOT EXISTS table_fky (id INTEGER PRIMARY KEY, datacol TEXT);
    CREATE TABLE IF NOT EXISTS table_fkz (id INTEGER PRIMARY KEY, datacol TEXT);
    CREATE TABLE IF NOT EXISTS table_main (
        id INTEGER PRIMARY KEY, 
      id_x INTEGER REFERENCES table_fkx(id), 
        id_y INTEGER REFERENCES table_fky(id), 
        id_z INTEGER REFERENCES table_fkz(id), 
        UNIQUE(id, id_x, id_y, id_z)
    );
    /*
    CREATE TRIGGER [autoincrement]
             AFTER INSERT
                ON table_main
              WHEN NEW.id IS NULL
    BEGIN
        UPDATE table_main
            SET id = IFNULL((SELECT MAX(id) FROM table_main) + 1, 0),
            id_x = IFNULL((SELECT MAX(id_x) FROM table_main) + 1, 0),
            id_y = IFNULL((SELECT MAX(id_y) FROM table_main) + 1, 0),
            id_z = IFNULL((SELECT MAX(id_z) FROM table_main) + 1, 0);
    END;
    */
    
    INSERT INTO table_fkx VALUES (10,'some data'),(33,'more data'),(56,'even more data');
    INSERT INTO table_fky VALUES (73,'some data'),(1200,'more data'),(560,'even more data');
    INSERT INTO table_fkz VALUES (15,'some data'),(1500,'more data'),(123456,'even more data');
    INSERT INTO table_main (id_x,id_y,id_z) VALUES 
        (10,1200,15),(56,1200,15),(33,560,15),(10,73,15) -- etc
    ;
    -- INSERT what could be a considered a duplicate but now is not as the autoincremnt(sic) makes it unique
    INSERT INTO table_main (id_x,id_y,id_z) VALUES (33,560,15); -- i.e. same as 3rd
    SELECT * FROM table_main 
        JOIN table_fkx ON id_x = table_fkx.id 
        JOIN table_fky ON id_y = table_fky.id
        JOIN table_fkz ON id_z = table_fkz.id
    ;
    

        2
  •  1
  •   DinoCoderSaurus    6 年前

    也许不是 尽管 因为 扳机。

    此更新 全部的 中的行 table_main 到同一个键(当 NEW.id 为空)。当数据中有2行(或更多)行时,这肯定会导致违反约束 主表

    UPDATE table_main
            SET id = IFNULL((SELECT MAX(id) FROM table_main) + 1, 0),
            id_x = IFNULL((SELECT MAX(id_x) FROM table_main) + 1, 0),
            id_y = IFNULL((SELECT MAX(id_y) FROM table_main) + 1, 0),
            id_z = IFNULL((SELECT MAX(id_z) FROM table_main) + 1, 0);
    

    如果 新建.id 如果不为null,那么问题就出在其他地方。

    推荐文章