简体   繁体   English

PostgreSQL,MonetDB和MySQL向现有表添加外键

[英]PostgreSQL, MonetDB and MySQL add foreign key to existing table

When I add a foreign key to a table that already has data, what does each of these database management systems do? 当我将外键添加到已经有数据的表中时,这些数据库管理系统分别做什么?

Do they analyze each value of the column to confirm it is a value from the referenced table primary key ? 他们是否分析列的每个值以确认它是来自引用表主键的值?

Or do they have some other optimized mechanism ? 还是他们有其他一些优化的机制? And if that's the case, what is that mechanism ? 如果是这样,那是什么机制?

I can't confirm for MonetDB, but in PostgreSQL and MySQL (and most probably on MonetDB too) the answer is yes, they will check every value and will raise an error if the key does not exists on the referenced table. 我无法确认是否使用MonetDB,但是在PostgreSQL和MySQL(以及很可能也是在MonetDB上)中,答案是肯定的,如果键在引用表中不存在,它们将检查每个值,并会引发错误。

Notice that the referenced column doesnt need to be the primary key for the referenced table - you can reference any column as a foreign key to the other table. 请注意,被引用的列不必是被引用表的主键-您可以将任何列作为另一个表的外键进行引用。

Yes, of course, a constraint that is not enforced would make no sense. 是的,当然,没有强制执行的约束是没有意义的。 You can just try(this is for Postgres): 您可以尝试一下(这是针对Postgres的):


DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE one
        ( one_id SERIAL NOT NULL PRIMARY KEY
        , name varchar
        );
INSERT INTO one(name)
SELECT 'name_' || gs::text
FROM generate_series(1,10) gs ;

CREATE TABLE two
        ( two_id SERIAL NOT NULL PRIMARY KEY
        , one_id INTEGER -- REFERENCES one(one_id)
        );

INSERT INTO two(one_id)
SELECT one_id
FROM one ;

DELETE FROM one WHERE one_id%5=0;

ALTER TABLE two
        ADD FOREIGN KEY (one_id) REFERENCES one(one_id)
        ;

\d one
\d two

Result: 结果:


NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to table tmp.one
drop cascades to table tmp.two
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 10
CREATE TABLE
INSERT 0 10
DELETE 2
ERROR:  insert or update on table "two" violates foreign key constraint "two_one_id_fkey"
DETAIL:  Key (one_id)=(5) is not present in table "one".
                                  Table "tmp.one"
 Column |       Type        |                      Modifiers                       
--------+-------------------+------------------------------------------------------
 one_id | integer           | not null default nextval('one_one_id_seq'::regclass)
 name   | character varying | 
Indexes:
    "one_pkey" PRIMARY KEY, btree (one_id)

                             Table "tmp.two"
 Column |  Type   |                      Modifiers                       
--------+---------+------------------------------------------------------
 two_id | integer | not null default nextval('two_two_id_seq'::regclass)
 one_id | integer | 
Indexes:
    "two_pkey" PRIMARY KEY, btree (two_id)

The error message is the same as for an actual insert or update. 该错误消息与实际插入或更新相同。 And you can see that the engine bails out once it en counters the first conflicting row. 您会看到,引擎在与第一行发生冲突时反响了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM