我有这个:
CREATE TABLE people
(
id bigserial,
timestamp timestamptz DEFAULT now() NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE "personal information"
(
id bigserial,
"person id" bigint NOT NULL,
timestamp timestamptz DEFAULT now() NOT NULL,
"data's timestamp" timestamptz,
"field" text NOT NULL,
"value" text,
PRIMARY KEY (id),
FOREIGN KEY ("person id") REFERENCES people (id) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO people RETURNING id; -- Syntax error.
INSERT INTO people; -- Syntax error.
Run Code Online (Sandbox Code Playgroud)
为什么我的插入失败?事实上,“people”表中的所有列都是自动的:该id
列是一个 bigserial,并且该列timestamp
始终设置为插入时的当前时间。因此,我不需要指定要插入的任何列,因为它们都是自动的。
那么为什么会出现语法错误呢?它要我做什么?这让我觉得好像我没有以某种方式正确地做这件事,但是在“人员”表中拥有一堆“个人数据”字段将是多余的,因为这些数据将存储在“个人信息”表中。例如,“字段”可能是“社会安全号码”或“名字”,所以我只获取该“人员 ID”的最新记录(基于时间戳)以获取他们的社会安全号码或名字。
如果我将这些值作为列存储在“people”中,那将是毫无意义的冗余,而且每当我将来引入一种新的“个人信息字段”时,它都会使它成为一个主要的 PITA,因为我必须这样做将列添加到“人员”表。所以我真的希望我的高效和智能 (IMO) 结构不会与 PostgreSQL 不兼容,而且我只是缺少一些小的语法细节。
a_h*_*ame 23
语法规则要求至少指定一个目标列。如果您想让所有列的默认值“生效”,您可以使用该default values
子句。
INSERT INTO people DEFAULT VALUES;
Run Code Online (Sandbox Code Playgroud)
另一种选择是为一列提供DEFAULT
子句:
insert into people ("timestamp") values (default);
Run Code Online (Sandbox Code Playgroud)
一种方法如下:
CREATE TABLE people
(
id bigserial,
timestamp timestamptz DEFAULT now() NOT NULL,
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
进而:
INSERT INTO people (timestamptz) VALUES (NOW()) RETURNING id;
Run Code Online (Sandbox Code Playgroud)
看来一个INSERT
子句必须至少有一个值,尽管正如您所指出的,DEFAULT NOW()
在这种特殊情况下,它使表中的声明变得多余!
看来您在 PostgreSQL 中发现了一个(非常)边缘情况的错误(+1)!
更新:
按照 @a_horse_with_no_name 的出色答案,出于演示目的,我将他的解决方案包含在此处的新小提琴中。
有几点:
你应该(为了你自己的理智)永远不要使用 SQL 关键字作为表名或列名
你的EAV系统(正如@Martin Smith所指出的)是有缺陷的 - 如果你有一个名为的字段age_in_years
- 你可以将其设为 aSMALLINT
并进一步添加CHECK
约束(age_in_years >= 0
和<= 120
),然后优化器(通常)可以生成更好的计划涉及该字段的任何查询 - 这几乎适用于所有字段,再加上(已经提到的)您的查询将很快变得非常麻烦的事实!
ps 一如既往,欢迎来到论坛!
归档时间: |
|
查看次数: |
4743 次 |
最近记录: |