无法插入数据,PostgreSQL上的外键错误

时间:2018-11-19 19:46:31

标签: sql postgresql sql-insert

我有3个表,其中表INTRUSIONS具有属于CCTVS和ALARMS表的外键。我希望外键在我的INTRUSIONS表中可以为空。我不确定为什么,但是无法将数据插入“ INTRUSIONS”表中。这是我的代码:

CREATE  TABLE
REMOTE_SECURITY.CCTVS(CCTV_ID   serial);

CREATE  TABLE
REMOTE_SECURITY.ALARMS(ALARM_ID serial);

CREATE  TABLE
REMOTE_SECURITY.INTRUSIONS(INTRUSION_ID serial,CCTV_ID  serial,ALARM_ID serial);

ALTER   TABLE
REMOTE_SECURITY.CCTVS   ADD CONSTRAINT
CCTVS_PK    PRIMARY KEY
(CCTV_ID)
;
ALTER   TABLE
REMOTE_SECURITY.ALARMS  ADD CONSTRAINT
ALARMS_PK   PRIMARY KEY
(ALARM_ID)
;

此代码无效:

  INSERT
    INTO
        REMOTE_SECURITY.INTRUSIONS
    (
        INTRUSION_ID
    ,   CCTV_ID
    ,   ALARM_ID
    ) VALUES (
        1
    ,   NULL
    ,   1
    )
    ;

这是错误:

[2018-11-19 19:35:59] [23502] ERROR: null value in column "cctv_id" violates not-null constraint
[2018-11-19 19:35:59] Detail: Failing row contains (1, null, 1, 2010-02-01 07:00:01).

3 个答案:

答案 0 :(得分:0)

外键强制该列为非null。如果您想要一个外键关联,它将不知道如何将null与另一个表关联。从文档中

  

外键约束指定一列(或一组列)中的值必须与另一个表的某一行中出现的值匹配。我们说这保持了两个相关表之间的参照完整性。

https://www.postgresql.org/docs/9.4/ddl-constraints.html

答案 1 :(得分:0)

您的Error很清楚。您不能将Null的值设置为Foreign KeySerial。.也许在概念设计中您的schema是错误的..

CREATE TABLE tablename (
    colname SERIAL
);

等同于指定:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

Documentation Serial数据类型保留Not Null,因此不能为Null,而其他答案确实很好地说明了约束外键。

Documentation FK

  

我们说这保持了两个相关对象之间的参照完整性   桌子

所以。FK中的值引用的是PK的“父对象”值。PK不能有Null,所以FK也是如此。

答案 2 :(得分:0)

外键列(在您的情况下为intrusions.cctv_idintrusions.alarm_id)不应定义为serial,因为您不想生成新值每次插入它们时。您使用引用的主键列中生成的值

如dwir182所指出的,serial列被隐式定义为not null。通过修正错误的FK列定义,您将能够插入NULL值。

所以你想要

CREATE TABLE remote_security.intrusions
(
  intrusion_id   serial,
  -- no serial for the foreign key columns!
  cctv_id        integer references cctvs,
  alarm_id       integer references alarms
);

然后您可以执行以下操作:

insert into remote_security.cctvs values (default); -- creates id = 1;
insert into remote_security.alarms values (default); -- creates id = 1;

-- do not specify a value for the serial column!
insert into remote_security.intrusions 
  (intrusion_id, cctv_id, alarm_id)
values 
  (default, null, 1);

请参见在线示例:https://rextester.com/ELPHK12991