webentwicklung-frage-antwort-db.com.de

es ist möglich, eine Spalte als mehrere Fremdschlüssel zu referenzieren

Ich habe einige Tabellen und möchte eine Spalte aus der Tabelle PDF auf mehrere andere Tabellen verweisen.enter image description here

zum Beispiel, wenn die Ausgabe von PDF -Tabelle select folgendermaßen aussieht:

ITEM_TYPE  ITEM_ID  QUANTITY

1          23       3
2          12       1

es sagt mir:

PDF hat 3 Autorad-Produkte und 1 Car-Vorlagenkopf oben;

Ich habe SQL-Code geschrieben, funktioniert aber nicht richtig:

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;

ist es möglich, es zu erstellen?

20
insict

Nein.

Das heißt, Sie können auf diese Weise keine Fremdschlüsseleinschränkung erstellen. Sie können jedoch einen Fremdschlüssel ohne eine Fremdschlüsseleinschränkung verwenden.

Ein Fremdschlüssel ist nur der Wert des Primärschlüssels einer anderen Tabelle (oder eines anderen Datensatzes in derselben Tabelle), der in Joins verwendet werden kann. Sie können auch andere Felder als den Primärschlüssel referenzieren, wenn Sie nur den Wert für Joins verwenden müssen.

Eine Fremdschlüsseleinschränkung weist die Datenbank jedoch an, die Regel zu erzwingen, dass die referenzierte Tabelle für jeden Fremdschlüsselwert in einer Tabelle einen Datensatz mit dem Primärschlüssel enthält. Das Erzwingen, dass jeder Fremdschlüssel in der Tabelle PDF einen Primärschlüssel IN ALL VIER TABLES hat, funktioniert für Sie nicht. Fahren Sie also fort und verwenden Sie das Feld, um auf andere Datensätze zu verweisen, erstellen Sie jedoch einfach keine Fremdschlüsseleinschränkung.

22
Marlin Pierce

Das Problem, das Sie gefunden haben, heißt Polymorphic Associations

Bitte stellen Sie diese Frage: MySQL - Bedingte Fremdschlüsseleinschränkungen

4
Browny Lin

Es sollte möglich sein. Ein mögliches Problem ist, dass Ihre drei Fremdschlüsseleinschränkungen denselben Namen haben. 

2
Dan Bracuk

Nein, ein Fremdschlüsselfeld soll auf eine Tabelle verweisen.

Wenn Sie die FK-Einschränkungen wie beschrieben hatten, referenziert ein item_id-Feld in allen drei Tabellen auf denselben Primärschlüsselwert. Es ist sehr wahrscheinlich, dass der gewünschte Primärschlüssel in den drei verschiedenen Tabellen unterschiedliche Primärschlüssel hat.

Sie möchten, dass ein Datensatz (Zeile) auf Datensätze in den Tabellen Product, Header und Service verweist. Dazu verwenden Sie drei verschiedene Felder, eines für jeden Fremdschlüssel.

Ich bemerke auch, dass die Artikeltabelle die drei Fremdschlüssel benötigt hat. Die Tabelle PDF könnte ein Feld enthalten, das auf Artikel verweist, und der Datensatz in Artikel verweist auf die drei anderen Tabellen.

1
Marlin Pierce

ihr möglicher Fremdschlüsseleinschränkungsname sollte sich wie folgt unterscheiden: __. Primärschlüssel- und Fremdschlüsseltabellenspalte sollten denselben Datentyp wie folgt haben.

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$$
0
Rahul Pandey

Theoretisch können Sie nicht mehrere Fremdschlüssel für eine einzelne Spalte erzwingen. Alternativ können Sie dies auch mithilfe von Prozeduren erzwingen, bei denen Sie die in mehreren Tabellen vorhandenen Eingaben überprüfen und die erforderliche Operation ausführen Die Tabelle sollte von den Prozeduren durchgeführt werden, die die erforderliche Bedingung validieren, andernfalls würde dies zu einer Verletzung der Integrität führen.

0
acsinha

Ja es ist möglich. Auch wenn es ein bisschen seltsam erscheint.

Zuerst möchte ich einen Screenshot meiner MySQL Workbench zeigen, um zu beweisen, dass es funktioniert.

 Table editor

... und für diejenigen, die sagen "Vielleicht haben Sie vergessen, die Änderungen anzuwenden" ... Hier ist der Screenshot des Schemabrowsers:

 Schema browser

und schließlich der exportierte Dump mit einigen Beispieldaten:

-- 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 @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @[email protected]@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @[email protected]@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 [email protected]_TIME_ZONE */;

/*!40101 SET [email protected]_SQL_MODE */;
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */;
/*!40101 SET [email protected]_CHARACTER_SET_RESULTS */;
/*!40101 SET [email protected]_COLLATION_CONNECTION */;
/*!40111 SET [email protected]_SQL_NOTES */;

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

Verwenden Sie 'Data Import/Restore' in MySQL Workbench, wenn Sie es anstelle eines SQL-Skript-Editors testen möchten.

, ABER Sie sollten kein Auto-Inkrement für die product-, header- und service-Tabellen verwenden, auf die mit pdf_created.item_id verwiesen wird, da dies ein glücklicher Zufall wäre, wenn alle drei dieselbe ID erhalten. Sie sollten die ID (die ID des Elements) zuweisen.

0
René Link