2017-03-04 131 views
1

您能否介绍为什么CHARGEITEM,INVOICE和PAYMENT可能会失败?我在这里错过了什么?MySQL 1215:无法添加外键约束

我检查了这些:

  • 所有的PK和FKS是BIGINT列
  • 我让他们空列
  • 删除了约束名称(想他们可能会发生冲突)
  • 新增的ON DELETE RESTRICT
  • 我也检查过他们都是INNODB。

以下是完整的脚本(表6,8和9是失败):

CREATE TABLE `BUILDING` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `NAME` varchar(255) DEFAULT NULL, 
    `ADDRESS` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


CREATE TABLE `ROOM` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `BUILDINGID` BIGINT NULL DEFAULT NULL, 
    `FLOORNUM` varchar(255) DEFAULT NULL, 
    `DOORNUM` varchar(255) DEFAULT NULL, 
    `TYPE` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `BUILDINGID` (`BUILDINGID`), 
    FOREIGN KEY (`BUILDINGID`) REFERENCES `BUILDING` (`ID`) ON DELETE RESTRICT 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `BOOKING` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `ENTRYDATE` datetime DEFAULT NULL, 
    `GUESTNAME` varchar(255) DEFAULT NULL, 
    `GUESTCONTACT` varchar(255) DEFAULT NULL, 
    `GUESTADDRESS` varchar(255) DEFAULT NULL, 
    `GUESTIDTYPE` varchar(255) DEFAULT NULL, 
    `GUESTIDNUM` varchar(255) DEFAULT NULL, 
    `GUESTPASSPORTNUM` varchar(255) DEFAULT NULL, 
    `NOTES` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `BOOKINGROOM` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `BOOKINGID` BIGINT NULL DEFAULT NULL, 
    `ROOMID` BIGINT NULL DEFAULT NULL, 
    `STARTDATE` date DEFAULT NULL, 
    `ENDDATE` date DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `BOOKINGID` (`BOOKINGID`), 
    KEY `ROOMID` (`ROOMID`), 
    FOREIGN KEY (`BOOKINGID`) REFERENCES `BOOKING` (`ID`) ON DELETE RESTRICT, 
    FOREIGN KEY (`ROOMID`) REFERENCES `ROOM` (`ID`) ON DELETE RESTRICT 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


CREATE TABLE `CHARGE` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `CHARGEGROUP` varchar(255) DEFAULT NULL, 
    `CHARGECODE` varchar(255) DEFAULT NULL, 
    `NOTES` varchar(255) DEFAULT NULL, 
    `UNIT` varchar(255) DEFAULT NULL, 
    `UNITRATE` double NOT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `CHARGEITEM` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `BOOKINGID` BIGINT NULL DEFAULT NULL, 
    `ROOMID` BIGINT NULL DEFAULT NULL, 
    `CHARGEID` BIGINT NULL DEFAULT NULL, 
    `ENTRYSTAFFID` BIGINT NULL DEFAULT NULL, 
    `ENTRYDATE` datetime DEFAULT NULL, 
    `VALUEDATE` date DEFAULT NULL, 
    `UNIT` varchar(255) DEFAULT NULL, 
    `UNITRATE` double NOT NULL, 
    `UNITS` double NOT NULL, 
    `AMOUNT` double NOT NULL, 
    `NOTES` varchar(255) DEFAULT NULL, 
    `INVOICEID` BIGINT NULL DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `INVOICEID` (`INVOICEID`), 
    KEY `ROOMID` (`ROOMID`), 
    KEY `BOOKINGID` (`BOOKINGID`), 
    KEY `CHARGEID` (`CHARGEID`), 
    FOREIGN KEY (`INVOICEID`) REFERENCES `INVOICE` (`ID`) ON DELETE RESTRICT, 
    FOREIGN KEY (`ROOMID`) REFERENCES `ROOM` (`ID`) ON DELETE RESTRICT, 
    FOREIGN KEY (`BOOKINGID`) REFERENCES `BOOKING` (`ID`) ON DELETE RESTRICT, 
    FOREIGN KEY (`CHARGEID`) REFERENCES `CHARGE` (`ID`) ON DELETE RESTRICT 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `DROPDOWNENTRY` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `MODULE` varchar(255) DEFAULT NULL, 
    `POSITION` int(11) NOT NULL, 
    `KEY` varchar(255) DEFAULT NULL, 
    `VALUE` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `INVOICE` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `BOOKINGID` varchar(255) NOT NULL, 
    `ENTRYSTAFFID` BIGINT NULL DEFAULT NULL, 
    `ENTRYDATE` datetime DEFAULT NULL, 
    `AUTHSTAFFID` BIGINT NULL DEFAULT NULL, 
    `AUTHDATE` datetime DEFAULT NULL, 
    `NETAMOUNT` double NOT NULL, 
    `TAX1` double NOT NULL, 
    `TAX2` double NOT NULL, 
    `TAX3` double NOT NULL, 
    `TOTALTAX` double NOT NULL, 
    `TOTALINCLTAX` double NOT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `BOOKINGID` (`BOOKINGID`), 
    FOREIGN KEY (`BOOKINGID`) REFERENCES `BOOKING` (`ID`) ON DELETE RESTRICT 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `PAYMENT` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `INVOICEID` BIGINT NULL DEFAULT NULL, 
    `AMOUNTPAID` double NOT NULL, 
    `PAYMODE` varchar(255) DEFAULT NULL, 
    `ENTRYDATE` datetime DEFAULT NULL, 
    `VALUEDATE` date DEFAULT NULL, 
    `REALISATIONDATE` date DEFAULT NULL, 
    `BANKCODE` varchar(255) DEFAULT NULL, 
    `INSTRUMENTNUM` varchar(255) DEFAULT NULL, 
    `POSCODE` varchar(255) DEFAULT NULL, 
    `REALISATIONSTATUS` varchar(255) DEFAULT NULL, 
    `NOTES` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `INVOICEID` (`INVOICEID`), 
    FOREIGN KEY (`INVOICEID`) REFERENCES `INVOICE` (`ID`) ON DELETE RESTRICT 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `RESERVATION` (
    `ID` BIGINT NOT NULL AUTO_INCREMENT, 
    `ENTRYDATE` datetime DEFAULT NULL, 
    `FROMDATE` date DEFAULT NULL, 
    `TODATE` date DEFAULT NULL, 
    `NUMROOMS` int(11) NOT NULL, 
    `GUESTNAME` varchar(255) DEFAULT NULL, 
    `GUESTCONTACT` varchar(255) DEFAULT NULL, 
    `GUESTADDRESS` varchar(255) DEFAULT NULL, 
    `NOTES` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
+0

试着做那么*非空的* – Psi

+0

尝试在创建所有表之后添加外键 –

+0

@Psi至少有一些需要根据我的用例为空。例如,没有分组的费用将不会有发票编号 – Teddy

回答

3

两个问题:当你在另一个表指存在

  • INVOICES犯规。在引用之前定义表格或在创建所有表格后定义约束。
  • INVOICES表中,您正在定义数据类型varchar(255),但在外键中,它指向一个bigint列 - 不起作用。

    INVOICES表,

    `BOOKINGID` varchar(255) NOT NULL, 
    

    将其更改为:

    `BOOKINGID` BIGINT NOT NULL, 
    

固定都在这里 -

http://rextester.com/JAZOUD38011

+0

哦!我错过了。我改变了数列的数据类型! – Teddy

+0

来自MySQL的非常差的错误消息。花了这么多时间来修改一些FK列的数据类型:( – Teddy

+0

@Teddy - 你应该一个一个地执行它。这样你就会知道发生了什么错误。 – GurV

1

你的问题就在这里:

ON DELETE RESTRICT:如果在该表中的记录是不指向现有的主键,约束创建将失败。这包括null-值。

当你说你需要可为空值的时候,它不起作用。要么将您的约束设置为ON RESTRICT SET NULL,要么将字段设置为NOT NULL

+0

对于您的第一个要点,它是一个新的模式。所有表格都是新鲜的,没有任何数据!我不确定我是否理解第二个... – Teddy

+0

我将研究限制集null – Teddy

+0

另请检查有关前向声明的其他答案。 – Psi

2

数据库不支持转发外键引用。在CHARGEITEM比如你有:

FOREIGN KEY (`INVOICEID`) REFERENCES `INVOICE` (`ID`) ON DELETE RESTRICT, 

然而,INVOICECHARGEITEM后创建。因此,这会失败,等等。

两个选项:

  • 排队的表,以便它们引用之前创建它们。请注意,这并非总是可行,因为您的数据模型可以有循环引用。
  • 首先定义所有表,然后使用alter table add constraint定义所有外键引用。
+0

在订单错误的情况下,脚本会在首次运行时错过一些表格。但是,如果我一次又一次地运行相同的脚本,应该创建缺失的表。另外,即使我单独执行创建语句,它仍然会失败。 – Teddy