Has*_*aig 17 postgresql foreign-key alter-table
我有以下表格,
CREATE TABLE users (id int PRIMARY KEY);
-- already exists with data
CREATE TABLE message ();
Run Code Online (Sandbox Code Playgroud)
我如何改变messages
表格,
sender
被添加到其中sender
引用users
表的外键在哪里这没有用
# ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
ERROR: column "sender" referenced in foreign key constraint does not exist
Run Code Online (Sandbox Code Playgroud)
这个语句也不会创建列吗?
Vér*_*ace 23
您只需要添加另一个步骤 - 事实上 PostgreSQL 已经告诉您:column "sender" referenced in foreign key constraint does not exist
.
该FOREIGN KEY
(又名parent
)列必须已经存在,以使它的FK
。
我做了以下(从这里和文档)。请注意,父列必须有一个UNIQUE
约束(或者是PRIMARY KEY
),但它不一定是NOT NULL
。这是因为NULL
s 彼此不相等,也不等于其他任何东西 - 每个都NULL
被视为UNIQUE
自己的权利!
CREATE TABLE x(a INT UNIQUE NOT NULL);
CREATE TABLE y(b INT);
ALTER TABLE y ADD COLUMN c INT NOT NULL
CONSTRAINT y_x_fk_c REFERENCES x (a) -- if x (a) doens't exist, this will fail!
ON UPDATE CASCADE ON DELETE CASCADE; -- or other Referential Integrity Action
Run Code Online (Sandbox Code Playgroud)
需要注意的几点(请参阅此处的小提琴) - 尝试将不在 x (a) 中的值插入 y (c) 中失败,并且错误消息中给出了约束名称。
小提琴NOT NULL
对 x (a) 和 y (c)有约束。除非我有真正令人信服的理由,否则我总是将我的列声明为NOT NULL
- 它有助于优化器并减少混淆/错误的可能性。你可以用小提琴来试验自己,看看当你省略NOT NULL
一个(和两个)字段时会发生什么- 行为并不总是直观明显!
总是给你的外键起有意义的名字。被告知密钥“SYS_C00308108”被违反并不是很有帮助。在这些情况下,请参阅此处的小提琴,了解 Oracle 在这些情况下的行为,密钥名称因小提琴而异,但是以 SYS_... 开头的任意字符串(在长 dbfiddle 生成的表名之后)。
埃文·卡罗尔在他的答案在这里认为,自动生成的名字是好的-我已经证明这是为什么不为Oracle是一个好主意(至少高达18℃),但我也觉得这不是对PostgreSQL无论是一个好主意-如果没有别的,便携性的潜在问题。
我想信贷埃文·卡罗尔的指出了新领域的增加,并在FOREIGN KEY
创建和CONSTRAINT
(与指定的名称)可以在一个步骤中添加,而不是两个步骤我原来说的) -所以,请给他的信用为如果你想给我点赞——不过我会更详细地介绍。
考虑到您的问题中的陈述:
ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
Run Code Online (Sandbox Code Playgroud)
如果 RDBMS 可以使用与引用字段匹配的数据类型自动创建您想要的字段,那将是一个“不错的选择”。
我想说的是,更改 DDL 是(或至少应该是)很少使用的操作,而不是您想要定期执行的操作。它还冒着增加已经相当重要的文档的风险。
至少 PostgreSQL 尝试做一些合理的事情——它将表名、FOREIGN KEY
字段名和fkey
. 此外,当您自己命名约束时,错误消息将添加DETAIL: Key (c)=(7) is not present in table "x".
以提供对人类可能有意义的东西(与 Oracle 不同 - 请参阅 PostgreSQL fiddle的结尾)。
Eva*_*oll 12
我不知道为什么每个人都告诉你必须分两步完成。事实上,你没有。您尝试添加 a FOREIGN KEY
,它根据设计假定该列存在,如果该列不存在,则会引发该错误。如果添加COLUMN
,则可以FOREIGN KEY
使用REFERENCES
,
ALTER TABLE message
ADD COLUMN sender INT
REFERENCES users; -- or REFERENCES table(unique_column)
Run Code Online (Sandbox Code Playgroud)
会工作得很好。你可以看到ALTER TABLE
这里的语法,
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]
Run Code Online (Sandbox Code Playgroud)
以“行动”为,
ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
Run Code Online (Sandbox Code Playgroud)
这些例子甚至在文档中,
ALTER TABLE distributors
ADD CONSTRAINT distfk
FOREIGN KEY (address)
REFERENCES addresses (address);
ALTER TABLE distributors
ADD CONSTRAINT distfk
FOREIGN KEY (address)
REFERENCES addresses (address)
NOT VALID;
Run Code Online (Sandbox Code Playgroud)
但所有这些都不是必需的,因为我们可以依靠自动命名和主键解析(如果只指定了表名,那么您正在引用主键)。
归档时间: |
|
查看次数: |
52249 次 |
最近记录: |