请为我澄清两点:

外键可以为NULL吗? 外键可以被复制吗?

正如我所知道的那样,NULL不应该用于外键,但在我的一些应用程序中,我可以在Oracle和SQL Server中输入NULL,我不知道为什么。


当前回答

下面是一个使用Oracle语法的例子: 首先,让我们创建一个表COUNTRY

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

创建表PROVINCE

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

这在Oracle中运行得非常好。注意第二个表中的COUNTRY_ID外键没有“NOT NULL”。

现在要向PROVINCE表中插入一行,只需指定PROVINCE_ID就足够了。但是,如果您选择指定一个COUNTRY_ID,那么它必须已经存在于COUNTRY表中。

其他回答

外键可以为NULL吗?

现有的答案集中在单列场景。如果我们考虑多列外键,我们使用SQL标准中定义的MATCH [SIMPLE | PARTIAL | FULL]子句有更多的选项:

PostgreSQL-CREATE TABLE A value inserted into the referencing column(s) is matched against the values of the referenced table and referenced columns using the given match type. There are three match types: MATCH FULL, MATCH PARTIAL, and MATCH SIMPLE (which is the default). MATCH FULL will not allow one column of a multicolumn foreign key to be null unless all foreign key columns are null; if they are all null, the row is not required to have a match in the referenced table. MATCH SIMPLE allows any of the foreign key columns to be null; if any of them are null, the row is not required to have a match in the referenced table. MATCH PARTIAL is not yet implemented. (Of course, NOT NULL constraints can be applied to the referencing column(s) to prevent these cases from arising.)

例子:

CREATE TABLE A(a VARCHAR(10), b VARCHAR(10), d DATE , UNIQUE(a,b));
INSERT INTO A(a, b, d) 
VALUES (NULL, NULL, NOW()),('a', NULL, NOW()),(NULL, 'b', NOW()),('c', 'b', NOW());

CREATE TABLE B(id INT PRIMARY KEY, ref_a VARCHAR(10), ref_b VARCHAR(10));

-- MATCH SIMPLE - default behaviour nulls are allowed
ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) 
REFERENCES A(a,b) MATCH SIMPLE;

INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, 'b');  

-- (NULL/'x') 'x' value does not exists in A table, but insert is valid
INSERT INTO B(id, ref_a, ref_b) VALUES (2, NULL, 'x');  

ALTER TABLE B DROP CONSTRAINT IF EXISTS B_Fk; -- cleanup

-- MATCH PARTIAL - not implemented
ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) 
REFERENCES A(a,b) MATCH PARTIAL;
-- ERROR:  MATCH PARTIAL not yet implemented

DELETE FROM B; ALTER TABLE B DROP CONSTRAINT IF EXISTS B_Fk; -- cleanup

-- MATCH FULL nulls are not allowed
ALTER TABLE B ADD CONSTRAINT B_Fk FOREIGN KEY (ref_a, ref_b) 
REFERENCES A(a,b) MATCH FULL;

-- FK is defined, inserting NULL as part of FK
INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, 'b');
-- ERROR:  MATCH FULL does not allow mixing of null and nonnull key values.

-- FK is defined, inserting all NULLs - valid
INSERT INTO B(id, ref_a, ref_b) VALUES (1, NULL, NULL);

db < > fiddle演示

1 -是的,因为至少SQL Server 2000。

2 -是的,只要它不是UNIQUE约束或链接到唯一索引。

Yes foreign key can be null as told above by senior programmers... I would add another scenario where Foreign key will required to be null.... suppose we have tables comments, Pictures and Videos in an application which allows comments on pictures and videos. In comments table we can have two Foreign Keys PicturesId, and VideosId along with the primary Key CommentId. So when you comment on a video only VideosId would be required and pictureId would be null... and if you comment on a picture only PictureId would be required and VideosId would be null...

这取决于这个外键在关系中扮演什么角色。

如果这个外键也是你的关系中的键属性,那么它不能为NULL 如果这个外键是关系中的一个普通属性,那么它可以为NULL。

外键的思想是基于引用一个已经存在于主表中的值的概念。这就是为什么在另一个表中它被称为外键。这个概念被称为参考完整性。如果外键被声明为空字段,它将违反引用完整性的逻辑。它指的是什么?它只能引用主表中存在的内容。因此,我认为将外键字段声明为null是错误的。