根据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会发生冲突。
答案 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_sequence
,set the starting number on each node,以便生成的序列不会发生冲突。由于rowid
是SQLite是一个64位数字,你可以通过为每个节点生成一个唯一的32位数字(IP地址是一个方便的,可能是唯一的32位数字)并将其左移32位来实现这一点,或等效地,将其乘以4294967296。因此,64位rowid
实际上变为两个连接的32位数字NODE_ID, RECORD_ID
,保证不会发生冲突,除非一个节点生成超过40亿条记录。
答案 2 :(得分:1)
怎么样......
的假设
使用一个额外的列创建中央表,节点号...
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将始终是唯一的。