是否可以在Sqlite中对复合PK进行(模拟?)AUTOINCREMENT?

时间:2012-05-17 17:58:55

标签: sqlite auto-increment compound-key

根据SQLite docs,获取自动增量列的唯一方法是在主键上。

我需要一个复合主键,但我还需要自动递增。有没有办法在SQLite中实现这两个目标?

我将在PostgreSQL中编写表格的相关部分:

CREATE TABLE tstage (
    id                   SERIAL NOT NULL,
    node                 INT REFERENCES nodes(id) NOT NULL,
    PRIMARY KEY (id,node),
    -- ... other columns
);

此要求的原因是所有节点最终将其数据转储到单个集中节点,其中使用单列PK会发生冲突。

3 个答案:

答案 0 :(得分:2)

文档是正确的。 但是,可以在触发器中重新实现自动增量逻辑:

CREATE TABLE tstage (
    id    INT,  -- allow NULL to be handled by the trigger
    node  INT REFERENCES nodes(id) NOT NULL,
    PRIMARY KEY (id, node)
);

CREATE TABLE tstage_sequence (
    seq INTEGER NOT NULL
);
INSERT INTO tstage_sequence VALUES(0);

CREATE TRIGGER tstage_id_autoinc
AFTER INSERT ON tstage
FOR EACH ROW
WHEN NEW.id IS NULL
BEGIN
    UPDATE tstage_sequence
    SET seq = seq + 1;

    UPDATE tstage
    SET id = (SELECT seq
              FROM tstage_sequence)
    WHERE rowid = NEW.rowid;
END;

(如果有多个表,则使用带有表名的公共my_sequence表。)

答案 1 :(得分:1)

触发器有效,但很复杂。更简单地说,您可以避免串行ID。一种方法,您可以使用GUID。遗憾的是,我无法找到让SQLite默认为您生成GUID的方法,因此您必须在应用程序中生成它。还没有GUID类型,但您可以将其存储为字符串或a binary blob

或者,您的其他列中可能还有一些内容可用作合适的密钥。如果您知道插入的频率不会超过您选择的时间戳格式(SQLite offers several, see section 1.2)的分辨率,那么(node, timestamp_column)可能是一个很好的主键。

或者,您可以通过AUTOINCREMENT表使用SQLite的sqlite_sequenceset the starting number on each node,以便生成的序列不会发生冲突。由于rowid是SQLite是一个64位数字,你可以通过为每个节点生成一个唯一的32位数字(IP地址是一个方便的,可能是唯一的32位数字)并将其左移32位来实现这一点,或等效地,将其乘以4294967296。因此,64位rowid实际上变为两个连接的32位数字NODE_ID, RECORD_ID,保证不会发生冲突,除非一个节点生成超过40亿条记录。

答案 2 :(得分:1)

怎么样......

的假设

  • 只需要PK中的唯一性,而不是顺序性
  • 源表有PK

使用一个额外的列创建中央表,节点号...

CREATE TABLE tstage (
    node  INTEGER NOT NULL,
    id    INTEGER NOT NULL,   <<< or whatever the source table PK is
    PRIMARY KEY (node, id)
       :
);

将数据汇总到集中式节点时,将源节点的编号插入“node”并将“id”设置为源表的PRIMARY KEY列值...

INSERT INTO tstage (nodenumber, sourcetable_id, ...);

没有必要在中央表上维护另一个自动增量列,因为nodenumber + sourcetable_id将始终是唯一的。