2

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

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

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

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

这个要求的原因是所有节点最终都将他们的数据转储到一个集中的节点上,在这个节点上,使用单列 PK,会有冲突。

4

3 回答 3

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(或者如果有多个表,则使用带有表名的公共表。)

于 2013-01-04T10:41:55.170 回答
1

触发器有效,但很复杂。更简单地说,您可以避免使用序列号。一种方法,您可以使用GUID。不幸的是,我找不到让 SQLite 默认为您生成 GUID 的方法,因此您必须在应用程序中生成它。也没有 GUID 类型,但您可以将其存储为字符串或二进制 blob

或者,也许您的其他列中有一些东西可以作为合适的键。如果您知道插入不会比您选择的时间戳格式的分辨率更频繁(SQLite 提供了几种,请参阅第 1.2 节),那么也许(node, timestamp_column)是一个很好的主键。

或者,您可以使用 SQLite 的AUTOINCREMENT,但通过表在每个节点上设置起始编号,sqlite_sequence这样生成的序列就不会发生冲突。由于rowidSQLite 是一个 64 位数字,因此您可以通过为每个节点生成一个唯一的 32 位数字(IP 地址是一个方便的,可能是唯一的 32 位数字)并将其向左移动 32 位,或者等效地,将其相乘来做到这一点通过 4294967296。因此,64 位rowid实际上变成了两个连接的 32 位数字NODE_ID, RECORD_ID,保证不会发生冲突,除非一个节点生成超过 40 亿条记录。

于 2013-01-05T01:21:48.600 回答
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)
       :
);

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

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

无需在中央表上维护另一个自动递增列,因为 nodenumber+sourcetable_id 将始终是唯一的。

于 2013-01-05T13:56:21.030 回答