限制以防止在第三个表

时间:2016-07-12 22:13:24

标签: mysql sql foreign-keys composite

我可以在存储过程中实现我想要的约束,但是我想知道是否可以定义一组外键约束来完成这项工作。

我有几个表,这些关键关系:

NSNs
---
Id  PK

Solicitations
----
Id            PK
NSNId         FK - NSNs

Parts
-----
Id        PK
NSNId     FK - NSNs

BaseRFQs
-------
Id      PK
NSNId   FK - NSNs

RFQs
----
Id          PK
BaseRFQId   FK - BaseRFQs

BaseRFQsSols
------------
BaseRFQId PK/FK - BaseRFQs
SolId     PK/FK - Solicitations

RFQsSolsParts
-------------
RFQId     PK/FK - RFQs
SolId     PK/FK - Solicitations
PartId    PK/FK - Parts

我的问题是:

  1. 是否可以在BaseRFQsSols上设置外键约束,同时要求BaseRFQId和SolId引用具有相同NSNId的记录?
  2. 是否可以在RFQsSolsParts上设置外键约束,要求SolId和PartId引用具有相同NSNId的记录,要求RFQId引用与其具有相同NSNId的BaseRFQId另外两个?
  3. 我正在使用MySQL,虽然我理解它(如果我理解错误,请纠正我)我询问的CONSTRAINT FOREIGN KEY语法是ANSI兼容的,所以解决方案不应该在DBMS实现之间有所不同。

    编辑:根据@ Drew的请求,以下是现在的表格定义:

    CREATE TABLE `nsns` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NSN` char(16) NOT NULL,
      `Description` varchar(100) DEFAULT NULL,
      `ShortDesc` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`ID`),
      UNIQUE KEY `NSN_UNIQUE` (`NSN`)
    ) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin7
    
    CREATE TABLE `solicitations` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NSNId` int(11) NOT NULL,
      `UOMId` int(11) NOT NULL DEFAULT '1',
      `QUPId` int(11) NOT NULL DEFAULT '0',
      `SolicitationNo` char(16) NOT NULL,
      `Quantity` int(11) NOT NULL,
      `ReturnByDate` date NOT NULL,
      `StatusId` int(11) NOT NULL DEFAULT '1',
      `Memo` text,
      PRIMARY KEY (`ID`),
      UNIQUE KEY `SolicitationNo_UNIQUE` (`SolicitationNo`),
      KEY `NSN_idx` (`NSNId`)
      CONSTRAINT `NSNId` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin7
    
    CREATE TABLE `parts` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NSNId` int(11) NOT NULL,
      `VendorId` int(11) NOT NULL,
      `UOMId` int(11) NOT NULL DEFAULT '1',
      `QUPId` int(11) NOT NULL DEFAULT '1',
      `StatusId` int(11) DEFAULT '1',
      `PartNo` varchar(45) DEFAULT NULL,
      `Memo` text,
      PRIMARY KEY (`ID`)
      KEY `NSN_idx` (`NSNId`)
      CONSTRAINT `NSNId` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin7
    
    CREATE TABLE `baserfqs` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NSNId` int(11) NOT NULL,
      `BRFQNo` varchar(45) DEFAULT NULL,
      `Memo` text,
      `Finalized` bit(1) NOT NULL DEFAULT b'0',
      PRIMARY KEY (`ID`),
      UNIQUE KEY `BRFQNo_UNIQUE` (`BRFQNo`),
      KEY `NSN_idx` (`NSNId`),
      CONSTRAINT `NSNId` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin7
    
    CREATE TABLE `rfqs` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `BaseRFQId` int(11) NOT NULL,
      `VendorId` int(11) NOT NULL,
      `RFQNo` varchar(45) NOT NULL,
      `StatusId` int(11) NOT NULL DEFAULT '6',
      `DateSent` date DEFAULT NULL,
      `DateResponded` date DEFAULT NULL,
      `VendorNotes` text,
      `QuotedBy` varchar(45) DEFAULT NULL,
      `Title` varchar(45) DEFAULT NULL,
      `ValidityCodeId` int(11) DEFAULT '4',
      `UnitWt` decimal(10,3) DEFAULT NULL,
      `WtUOMId` int(11) DEFAULT '1',
      PRIMARY KEY (`ID`),
      UNIQUE KEY `RFQNo_UNIQUE` (`RFQNo`),
      KEY `BaseRFQId_idx` (`BaseRFQId`),
      KEY `VendorId_idx` (`VendorId`),
      KEY `StatusId_idx` (`StatusId`),
      KEY `ValidityCodeId_idx` (`ValidityCodeId`),
      KEY `WtUOMId_idx` (`WtUOMId`),
      CONSTRAINT `WtUOMId` FOREIGN KEY (`WtUOMId`) REFERENCES `wtuoms` (`ID`),
      CONSTRAINT `BaseRFQId` FOREIGN KEY (`BaseRFQId`) REFERENCES `baserfqs` (`ID`),
      CONSTRAINT `StatusId` FOREIGN KEY (`StatusId`) REFERENCES `rfqstatus` (`ID`),
      CONSTRAINT `ValidityCodeId` FOREIGN KEY (`ValidityCodeId`) REFERENCES `validitycodes` (`ID`),
      CONSTRAINT `VendorId` FOREIGN KEY (`VendorId`) REFERENCES `vendors` (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin7
    
    CREATE TABLE `baserfqssols` (
      `BaseRFQId` int(11) NOT NULL,
      `SolId` int(11) NOT NULL,
      `LineItemNo` int(11) NOT NULL DEFAULT '1',
      PRIMARY KEY (`BaseRFQId`,`SolId`),
      KEY `RFQ_idx` (`BaseRFQId`),
      KEY `Solicitation_idx` (`SolId`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin7
    
    CREATE TABLE `rfqssolsparts` (
      `RFQId` int(11) NOT NULL,
      `SolId` int(11) NOT NULL,
      `PartId` int(11) NOT NULL,
      `CondId` int(11) NOT NULL,
      `UOMId` int(11) NOT NULL DEFAULT '1',
      `QUPId` int(11) NOT NULL DEFAULT '1',
      `UnitPrice` decimal(10,3) NOT NULL,
      `LeadTime` int(11) DEFAULT NULL,
      `LTCId` int(11) DEFAULT NULL,
      `SplsNSNId` int(11) DEFAULT NULL,
      `SetupCostInc` bit(1) NOT NULL DEFAULT b'0',
      `CertCostInc` bit(1) NOT NULL DEFAULT b'0',
      `MfgCerts` bit(1) NOT NULL DEFAULT b'0',
      `Altered` bit(1) NOT NULL DEFAULT b'0',
      `OrigPkg` bit(1) NOT NULL DEFAULT b'1',
      `SplsContNo` varchar(45) DEFAULT NULL,
      `SplsDate` date DEFAULT NULL,
      PRIMARY KEY (`RFQId`,`SolId`,`PartId`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin7
    

1 个答案:

答案 0 :(得分:2)

我认为您的solIdsolitications。我原本以为它意味着坚固(就像一块石头)。所以,这可以通过合成完成。

请注意,提供的架构中存在一些拼写错误。一些丢失的逗号,一些用于编写索引名称。 MyISAM表已更改为INNODB。所以我做了一些重命名。此外,在table5周围有丢失的表。所以它不像你的脚本会运行(对于表rfqs)。

同样,由于您提供的表格丢失,以下架构将失败,大约60%到70%通过它。

到目前为止

表:

create schema slipper;
use slipper;

CREATE TABLE `nsns` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NSN` char(16) NOT NULL,
  `Description` varchar(100) DEFAULT NULL,
  `ShortDesc` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `NSN_UNIQUE` (`NSN`)
) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=latin7;

drop table if exists `solicitations`;
CREATE TABLE `solicitations` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NSNId` int(11) NOT NULL,
  `UOMId` int(11) NOT NULL DEFAULT '1',
  `QUPId` int(11) NOT NULL DEFAULT '0',
  `SolicitationNo` char(16) NOT NULL,
  `Quantity` int(11) NOT NULL,
  `ReturnByDate` date NOT NULL,
  `StatusId` int(11) NOT NULL DEFAULT '1',
  `Memo` text,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `SolicitationNo_UNIQUE` (`SolicitationNo`),
  KEY `NSN_idx1111` (`NSNId`),
  KEY `NSN_idx1112` (`ID`,`NSNId`), -- atm an necessary evil. Revisit, perhaps collapse one
  CONSTRAINT `NSNId` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin7;

drop table if exists `parts`;
CREATE TABLE `parts` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NSNId` int(11) NOT NULL,
  `VendorId` int(11) NOT NULL,
  `UOMId` int(11) NOT NULL DEFAULT '1',
  `QUPId` int(11) NOT NULL DEFAULT '1',
  `StatusId` int(11) DEFAULT '1',
  `PartNo` varchar(45) DEFAULT NULL,
  `Memo` text,
  PRIMARY KEY (`ID`),
  KEY `NSN_idx2222` (`NSNId`),
  KEY `NSN_idx2223` (`ID`,`NSNId`), -- atm an necessary evil. Revisit, perhaps collapse one
  CONSTRAINT `NSNId2222` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin7;

drop table if exists `baserfqs`;
CREATE TABLE `baserfqs` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NSNId` int(11) NOT NULL,
  `BRFQNo` varchar(45) DEFAULT NULL,
  `Memo` text,
  `Finalized` bit(1) NOT NULL DEFAULT b'0',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `BRFQNo_UNIQUE` (`BRFQNo`),
  KEY `NSN_idx4444` (`NSNId`),
  KEY `NSN_idx4445` (`ID`,`NSNId`), -- atm an necessary evil. Revisit, perhaps collapse one
  CONSTRAINT `NSNId4444` FOREIGN KEY (`NSNId`) REFERENCES `nsns` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin7;

CREATE TABLE `rfqs` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `BaseRFQId` int(11) NOT NULL,
  `VendorId` int(11) NOT NULL,
  `RFQNo` varchar(45) NOT NULL,
  `StatusId` int(11) NOT NULL DEFAULT '6',
  `DateSent` date DEFAULT NULL,
  `DateResponded` date DEFAULT NULL,
  `VendorNotes` text,
  `QuotedBy` varchar(45) DEFAULT NULL,
  `Title` varchar(45) DEFAULT NULL,
  `ValidityCodeId` int(11) DEFAULT '4',
  `UnitWt` decimal(10,3) DEFAULT NULL,
  `WtUOMId` int(11) DEFAULT '1',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `RFQNo_UNIQUE` (`RFQNo`),
  KEY `BaseRFQId_idx` (`BaseRFQId`),
  KEY `VendorId_idx` (`VendorId`),
  KEY `StatusId_idx` (`StatusId`),
  KEY `ValidityCodeId_idx` (`ValidityCodeId`),
  KEY `WtUOMId_idx` (`WtUOMId`),
  CONSTRAINT `WtUOMId` FOREIGN KEY (`WtUOMId`) REFERENCES `wtuoms` (`ID`),
  CONSTRAINT `BaseRFQId` FOREIGN KEY (`BaseRFQId`) REFERENCES `baserfqs` (`ID`),
  CONSTRAINT `StatusId` FOREIGN KEY (`StatusId`) REFERENCES `rfqstatus` (`ID`),
  CONSTRAINT `ValidityCodeId` FOREIGN KEY (`ValidityCodeId`) REFERENCES `validitycodes` (`ID`),
  CONSTRAINT `VendorId` FOREIGN KEY (`VendorId`) REFERENCES `vendors` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin7;


drop table if exists `compTableX001`;
CREATE TABLE `compTableX001`
(  -- a composition table for FK's in `baserfqssols`
  `ID` int(11) AUTO_INCREMENT PRIMARY KEY,
  `BaseRFQId` int(11) NOT NULL,     -- baserfqs.ID
  `SolId` int(11) NOT NULL,         -- solicitations.ID
  `NSNId` int(11) NOT NULL,
  unique key (`BaseRFQId`,`SolId`), -- no dupes allowed  
  CONSTRAINT `tx001_base` FOREIGN KEY (`BaseRFQId`,`NSNId`) REFERENCES `baserfqs` (`ID`,`NSNId`),
  CONSTRAINT `tx001_sol` FOREIGN KEY (`SolId`,`NSNId`) REFERENCES `solicitations` (`ID`,`NSNId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin7; 

drop table if exists `compTableX002`;
CREATE TABLE `compTableX002`
(  -- a composition table for FK's in `rfqssolsparts`
  `ID` int(11) AUTO_INCREMENT PRIMARY KEY,
  `BaseRFQId` int(11) NOT NULL,     -- baserfqs.ID
  `SolId` int(11) NOT NULL,         -- solicitations.ID
  `PartId` int(11) NOT NULL,        -- parts.ID
  `NSNId` int(11) NOT NULL,
  unique key (`BaseRFQId`,`SolId`,`PartId`), -- no dupes allowed 
  CONSTRAINT `tx002_base` FOREIGN KEY (`BaseRFQId`,`NSNId`) REFERENCES `baserfqs` (`ID`,`NSNId`),
  CONSTRAINT `tx002_sol` FOREIGN KEY (`SolId`,`NSNId`) REFERENCES `solicitations` (`ID`,`NSNId`),
  CONSTRAINT `tx002_part` FOREIGN KEY (`PartId`,`NSNId`) REFERENCES `parts` (`ID`,`NSNId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin7; 

drop table if exists `baserfqssols`;
CREATE TABLE `baserfqssols` (
  `ID` int(11) auto_increment,
  `compId` int(11) NOT NULL,    -- composition ID `compTableX001`.`ID`
  `LineItemNo` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`ID`),
  CONSTRAINT `basesol_compX001` FOREIGN KEY (`compId`) REFERENCES `compTableX001` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin7; -- changed engine type

-- Is it possible to set up a foreign key constraint on RFQsSolsParts that requires SolId and PartId to reference records
-- that have the same NSNId, and requires RFQId to reference a BaseRFQId which has the same NSNId as the other two?

drop table if exists `rfqssolsparts`;
CREATE TABLE `rfqssolsparts` (
  -- `RFQId` int(11) NOT NULL,      -- requirement BBBBBBBBBBBBB
  -- `SolId` int(11) NOT NULL,      -- requirement AAAAAAAAA
  -- `PartId` int(11) NOT NULL,     -- requirement AAAAAAAAA
  `ID` int(11) auto_increment,
  `compId` int(11) NOT NULL, -- composition ID `compTableX002`.`ID`
  `CondId` int(11) NOT NULL,
  `UOMId` int(11) NOT NULL DEFAULT '1',
  `QUPId` int(11) NOT NULL DEFAULT '1',
  `UnitPrice` decimal(10,3) NOT NULL,
  `LeadTime` int(11) DEFAULT NULL,
  `LTCId` int(11) DEFAULT NULL,
  `SplsNSNId` int(11) DEFAULT NULL,
  `SetupCostInc` bit(1) NOT NULL DEFAULT b'0',
  `CertCostInc` bit(1) NOT NULL DEFAULT b'0',
  `MfgCerts` bit(1) NOT NULL DEFAULT b'0',
  `Altered` bit(1) NOT NULL DEFAULT b'0',
  `OrigPkg` bit(1) NOT NULL DEFAULT b'1',
  `SplsContNo` varchar(45) DEFAULT NULL,
  `SplsDate` date DEFAULT NULL,
  -- PRIMARY KEY (`RFQId`,`SolId`,`PartId`) 
  PRIMARY KEY (`ID`),
  CONSTRAINT `triplet_compX002` FOREIGN KEY (`compId`) REFERENCES `compTableX002` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin7;

compTableX001就像一个名为ID的TwoParents-OneChild迷你层次结构。所以ID是父母的名字。它有两个父母(BaseRFQIdSolId)和一个孩子(NSNId)。名称或标识符ID是它支持的baserfqssols行的FK目标。 分别引用引用

同样,compTableX002似乎解决了问题2的现在条件。

<强>清理:

drop schema slipper;