是否可以创建两个具有不相交标识符的表?



By "disjoint"我指的是相互排斥的ID值集合。两个表之间没有重叠。
例如,两个表上id列的序列生成器应该一起工作,以确保它们总是不相交的。我不确定这是否可能。所以,我想我就在这里问一下。

<表类>id名称tbody><<tr>0abc1cad2垫3请愿

另一种破解方法:


CREATE TABLE odd(
id INTEGER GENERATED ALWAYS AS IDENTITY (START 1 INCREMENT 2)
, val integer
);

CREATE TABLE even(
id INTEGER GENERATED ALWAYS AS IDENTITY (START 2 INCREMENT 2)
, val integer
);
INSERT INTO odd (val)
SELECT GENERATE_SERIES(1,10);
INSERT INTO even (val)
SELECT GENERATE_SERIES(1,20);
SELECT * FROM odd;
SELECT * FROM even;

结果:


CREATE TABLE
CREATE TABLE
INSERT 0 10
INSERT 0 20
id | val 
----+-----
1 |   1
3 |   2
5 |   3
7 |   4
9 |   5
11 |   6
13 |   7
15 |   8
17 |   9
19 |  10
(10 rows)
id | val 
----+-----
2 |   1
4 |   2
6 |   3
8 |   4
10 |   5
12 |   6
14 |   7
16 |   8
18 |   9
20 |  10
22 |  11
24 |  12
26 |  13
28 |  14
30 |  15
32 |  16
34 |  17
36 |  18
38 |  19
40 |  20
(20 rows)

一个非常简单的方法是共享相同的SEQUENCE:

CREATE TABLE a (
id serial PRIMARY KEY
, name text
);
CREATE TABLE b (
id int PRIMARY KEY
, name text
);
SELECT pg_get_serial_sequence('a', 'id');  -- 'public.a_id_seq'
ALTER TABLE b ALTER COLUMN id SET DEFAULT nextval('public.a_id_seq');  -- !

db<此处小提琴>

这样表a"owns"序列,而表b从相同的来源提取。如果你愿意,你也可以创建一个独立的SEQUENCE

注意:只这保证互斥的新id(即使在并发写负载下),同时不重写默认值,以后也不更新它们。

相关:

  • 创建一个PostgreSQL序列到一个字段(不是记录的ID)
  • 使用串行主键列安全地重命名表
  • 自动递增表列
  • PostgreSQL下一个序列的值?

欢迎来到表间约束或断言的痛苦世界-这是ISO SQL和几乎所有RDBMS都无法从人体工程学角度处理的事情…

(虽然ISO SQL确实描述了延迟约束和数据库范围的断言,但据我所知,只有PostgreSQL实现了延迟约束,没有生产质量的RDBMS支持数据库范围的断言)


一种方法是有第三个表,它是只有表与SERIAL(又名IDENTITY又名AUTO_INCREMENT)的一个鉴别符列,结合形成表的主键,然后其他两个表有一个FK约束PK -但他们也需要相同的鉴别符列(与CHECK约束强制),但你永远不需要在大多数查询引用该列。

由于你的文章没有告诉我们真正的表名是什么,我将使用我自己的

像这样:

CREATE TABLE postIds (
postId   int     NOT NULL SERIAL,
postType char(1) NOT NULL, /* This is the discriminator column. It can only contain ONLY either 'S' or 'G' which indicates which table contains the rest of the data */
CONSTRAINT PK_postIds PRIMARY KEY ( postId, postType ),
CONSTRAINT CK_type CHECK ( postType IN ( 'S', 'G' ) )
);
CREATE TABLE shitposts (
postId   int     NOT NULL,
postType char(1) DEFAULT('S'),
foobar   nvarchar(255)     NULL,
etc      int           NOT NULL,
CONSTRAINT PK_shitpostIds PRIMARY KEY ( postId, postType ),
CONSTRAINT CK_type CHECK ( postType = 'S' ),
CONSTRAINT FK_shitpost_ids FOREIGN KEY ( postId, postType ) REFERENCES postIds ( postId, postType )
);
CREATE TABLE goldposts (
postId   int     NOT NULL,
postType char(1) DEFAULT('G'),
foobar   nvarchar(255)     NULL,
etc      int           NOT NULL,
CONSTRAINT PK_goldpostIds PRIMARY KEY ( postId, postType ),
CONSTRAINT CK_type CHECK ( postType = 'G' ),
CONSTRAINT FK_goldpost_ids FOREIGN KEY ( postId, postType ) REFERENCES postIds ( postId, postType )
)

使用这种设计,shitposts中的任何行都不可能与goldposts中的帖子共享postId值,反之亦然。

然而,可以在postIds中存在一行,而不需要goldpostsshitposts中都有任何行。幸运的是,当你使用PostgreSQL时,你可以postIds添加一个新的FK约束到goldpostsshitposts,但是使用延迟约束。

最新更新