40

我的表很少,我想将 PDF 表中的一列引用到其他多个表。 在此处输入图像描述

例如,如果 PDF 表格select输出如下所示:

ITEM_TYPE  ITEM_ID  QUANTITY

1          23       3
2          12       1

它告诉我:

PDF 上面有 3 个 Car Wheel Product 和 1 个 Car Template Header;

我写了 SQL 代码,但不能正常工作:

CREATE TABLE `pdf_created` (
    `id` INT(10) UNSIGNED NOT NULL UNIQUE AUTO_INCREMENT,
    `pdf_id` INT(10) NOT NULL,
    `item_type` INT(3) UNSIGNED NOT NULL,
    `item_id` INT(10) UNSIGNED NOT NULL,
    `quantity` INT(3) NOT NULL,
    PRIMARY KEY (`id`),
    KEY `FK_pdf_id` (`pdf_id`),
    CONSTRAINT `FK_pdf_id` FOREIGN KEY (`pdf_id`) REFERENCES `pdf` (`id`),
    KEY `FK_item_type` (`item_type`),
    CONSTRAINT `FK_item_type` FOREIGN KEY (`item_type`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
    KEY `FK_item_id` (`item_id`),
    CONSTRAINT `FK_item_id` FOREIGN KEY (`item_id`) REFERENCES `product` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT `FK_item_id` FOREIGN KEY (`item_id`) REFERENCES `service` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT `FK_item_id` FOREIGN KEY (`item_id`) REFERENCES `header` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `header` (
    `id` INT(10) UNSIGNED NOT NULL UNIQUE AUTO_INCREMENT,
    `title` VARCHAR(255),
    `desc` VARCHAR(65535),
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `service` (
    `id` INT(10) UNSIGNED NOT NULL UNIQUE AUTO_INCREMENT,
    `desc` VARCHAR(65535) NOT NULL,
    `price` DECIMAL(5,2) NOT NULL,
    `active` INT(1) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `product` (
    `id` INT(10) UNSIGNED NOT NULL UNIQUE AUTO_INCREMENT,
    `category_id` INT(3) UNSIGNED NOT NULL,
    `symbol` VARCHAR(255),
    `desc` VARCHAR(65535), 
    `price` DECIMAL(5,2) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

有可能创造吗?

4

8 回答 8

37

不。

也就是说,您不能以这种方式创建外键约束。但是,您可以使用没有外键约束的外键。

所有外键都是另一个表(或同一个表中的另一个记录)主键的值,可以在连接中使用。事实上,如果您只需要使用连接的值,您可以引用主键以外的字段。

但是,外键约束告诉数据库强制执行规则,即对于表中的每个外键值,所引用的表都有一条记录,该记录作为它的主键。强制 PDF 表中的每个外键在所有四个表中都有一个主键对您不起作用。所以继续使用该字段来引用其他记录,但不要创建任何外键约束。

于 2013-03-21T13:59:24.027 回答
13

你遇到的问题叫做Polymorphic Associations

请参考这个问题:MySQL - 条件外键约束

于 2014-03-11T08:12:22.100 回答
3

这应该是可能的。一个潜在的问题是您的三个外键约束具有相同的名称。

于 2013-03-21T12:22:04.930 回答
1

不,一个外键字段意味着引用一个表。

如果您确实有您描述的 FK 约束,那么 item_id 字段将在所有三个表中引用相同的主键值。三个不同表中所需的主键很可能具有不同的主键。

您想要的是一条记录(行)引用表产品、标题和服务中的记录。做到这一点的方法是使用三个不同的字段,每个外键一个。

我还注意到 Item 表具有所需的三个外键。您可以让 PDF 表有一个引用 Item 的字段,而 Item 中的记录引用其他三个表。

于 2013-03-21T12:30:32.077 回答
0

是的,它可能的外键约束名称应该像这样不同,主键和外键表列应该像这样具有相同的数据类型..

CREATE TABLE `neo_address_t` (
  `address_id` varchar(8) NOT NULL,
  `address_line_1` varchar(45) NOT NULL,
  `address_line_2` varchar(45) NOT NULL,
  `address_line_3` varchar(45) NOT NULL,
  `address_city` varchar(45) NOT NULL,
  `address_zipcode` varchar(45) NOT NULL,
  `address_state` varchar(45) NOT NULL DEFAULT 'Karnataka',
  `address_country` varchar(45) NOT NULL DEFAULT 'INDIA',
  `created_by` varchar(8) DEFAULT NULL,
  `created_on` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `last_modified_by` varchar(8) DEFAULT NULL,
  `last_modified_date` timestamp NULL DEFAULT '0000-00-00 00:00:00',
  `Refer_ID` int(11) DEFAULT NULL,
  `a_id` varchar(255) DEFAULT NULL,
  `referenceid` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`address_id`),
  KEY `hospital_ID_FK_idx` (`Refer_ID`),
  CONSTRAINT `Patient_ID_FK` FOREIGN KEY (`Refer_ID`) REFERENCES `neo_patient_t` (`patient_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `hospital_ID_FK` FOREIGN KEY (`Refer_ID`) REFERENCES `neo_hospital_t` (`hospital_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
  CONSTRAINT `staff_ID_FK` FOREIGN KEY (`Refer_ID`) REFERENCES `neo_staff_t` (`staff_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
)     
ENGINE=InnoDB DEFAULT CHARSET=utf8$$
于 2013-05-28T10:48:49.273 回答
0

从理论上讲,您不能在单个列上强制执行多个外键。或者,您可以使用验证多个表中存在的输入并执行必要操作的过程来强制执行此操作。请注意,该特定表上的所有操作都应由验证所需条件的过程完成,否则将导致违反完整性。

于 2016-04-08T06:29:49.193 回答
0

是的,这是可能的。即使这看起来有点奇怪。

首先,我想展示我的 MySQL Workbench 的屏幕截图,以证明它可以工作。

表格编辑器

...对于那些说“也许您忘记应用更改”的人...这是模式浏览器的屏幕截图:

模式浏览器

最后是带有一些示例数据的导出转储:

-- MySQL dump 10.13  Distrib 5.7.12, for Win64 (x86_64)
--
-- Host: localhost    Database: multiple_foreign_keys
-- ------------------------------------------------------
-- Server version   5.7.17-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `header`
--

DROP TABLE IF EXISTS `header`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `header` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `desc` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `header`
--

LOCK TABLES `header` WRITE;
/*!40000 ALTER TABLE `header` DISABLE KEYS */;
INSERT INTO `header` VALUES (42,'Header','Test Header');
/*!40000 ALTER TABLE `header` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `pdf_created`
--

DROP TABLE IF EXISTS `pdf_created`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `pdf_created` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pdf_id` int(10) NOT NULL,
  `item_type` int(3) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `quantity` int(3) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `fk_item_to_product_idx` (`item_id`),
  CONSTRAINT `fk_item_to_header` FOREIGN KEY (`item_id`) REFERENCES `header` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_item_to_product` FOREIGN KEY (`item_id`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_item_to_service` FOREIGN KEY (`item_id`) REFERENCES `service` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `pdf_created`
--

LOCK TABLES `pdf_created` WRITE;
/*!40000 ALTER TABLE `pdf_created` DISABLE KEYS */;
INSERT INTO `pdf_created` VALUES (1,2,5,42,1);
/*!40000 ALTER TABLE `pdf_created` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `product`
--

DROP TABLE IF EXISTS `product`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `product` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` int(3) unsigned NOT NULL,
  `symbol` varchar(255) DEFAULT NULL,
  `desc` varchar(255) DEFAULT NULL,
  `price` decimal(5,2) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `product`
--

LOCK TABLES `product` WRITE;
/*!40000 ALTER TABLE `product` DISABLE KEYS */;
INSERT INTO `product` VALUES (42,13,'product','desc',10.00);
/*!40000 ALTER TABLE `product` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `service`
--

DROP TABLE IF EXISTS `service`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `service` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `desc` varchar(255) NOT NULL,
  `price` decimal(5,2) NOT NULL,
  `active` int(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `service`
--

LOCK TABLES `service` WRITE;
/*!40000 ALTER TABLE `service` DISABLE KEYS */;
INSERT INTO `service` VALUES (42,'some service',5.00,1);
/*!40000 ALTER TABLE `service` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2018-08-27 10:31:41

如果您想测试它而不是 SQL 脚本编辑器,请在 MySQL Workbench 中使用“数据导入/恢复”。

但是product您不应该对,headerservice引用的表使用自动增量pdf_created.item_id,因为如果这三个都获得相同的 ID,那将是一个幸运的巧合。您应该分配 id(项目的 id)。

于 2018-08-27T08:44:34.073 回答
0

是的,这是可能的,您可以使用一列作为多个表的外键,但这也不是一个好习惯,因为您永远不会在需要使用这种方法的地方如此依赖,但为了学习,您可以使用这种类型的 SQL 查询可以完成这项工作;)

在此处输入图像描述

ALTER TABLEdemo4添加约束rel1外键 ( two) 引用demo1( id) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLEdemo4添加约束rel2外键 ( two) 引用demo2( id) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLEdemo4添加约束rel3外键 ( two) 引用demo3( id) ON DELETE RESTRICT ON UPDATE RESTRICT;

于 2021-11-03T07:40:39.227 回答