我正在学习关系数据库,并且在将两个表与具有多对多关系的助手关联时遇到问题。
我正在尝试将两个具有 varchar 字段作为主键的表关联起来,生成一个辅助表,但它给了我一个错误Cannot add foreign key constraint
我有一系列疑问: 1º 是否可以用 varchar 字段类型建立这种关系?我已经通过将字段更改为 INT 对其进行了测试,并且它可以正常工作。
2º 我试图将一个表与另一个从 1 到多个的表以及 varchar 数据类型相关联(如果它有效)。
编辑1:
我复制创造是句子。
-- MySQL Workbench Forward Engineering
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema inver
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema inver
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `inver` DEFAULT CHARACTER SET utf8 ;
USE `inver` ;
-- -----------------------------------------------------
-- Table `inver`.`users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `inver`.`users` (
`id_user` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL DEFAULT NULL,
`surname` VARCHAR(45) NULL DEFAULT NULL,
`email` VARCHAR(45) NULL DEFAULT NULL,
`password` VARCHAR(230) NULL DEFAULT NULL,
`role` VARCHAR(45) NULL DEFAULT NULL,
PRIMARY KEY (`id_user`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `inver`.`greenhouse`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `inver`.`greenhouse` (
`fiwareServicePath` VARCHAR(45) NOT NULL,
`metros` VARCHAR(45) NULL,
`lugar` VARCHAR(45) NULL,
`users_id_user` INT(11) NOT NULL,
INDEX `fk_greenhouse1_users1_idx` (`users_id_user` ASC),
PRIMARY KEY (`fiwareServicePath`),
CONSTRAINT `fk_greenhouse1_users1`
FOREIGN KEY (`users_id_user`)
REFERENCES `inver`.`users` (`id_user`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `inver`.`sensors`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `inver`.`sensors` (
`entityId` VARCHAR(45) NOT NULL,
`sensor_name` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_spanish_ci' NULL DEFAULT NULL,
PRIMARY KEY (`entityId`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_spanish_ci;
-- -----------------------------------------------------
-- Table `inver`.`sensors_has_greenhouse`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `inver`.`sensors_has_greenhouse` (
`sensors_entityId` VARCHAR(45) NOT NULL,
`greenhouse_fiwareServicePath` VARCHAR(45) NOT NULL,
PRIMARY KEY (`greenhouse_fiwareServicePath`, `sensors_entityId`),
INDEX `fk_sensors_has_greenhouse_greenhouse1_idx` (`greenhouse_fiwareServicePath` ASC),
INDEX `fk_sensors_has_greenhouse_sensors1_idx` (`sensors_entityId` ASC),
CONSTRAINT `fk_sensors_has_greenhouse_sensors1`
FOREIGN KEY (`sensors_entityId`)
REFERENCES `inver`.`sensors` (`entityId`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_sensors_has_greenhouse_greenhouse1`
FOREIGN KEY (`greenhouse_fiwareServicePath`)
REFERENCES `inver`.`greenhouse` (`fiwareServicePath`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_spanish_ci;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
编辑2
我添加错误:
Executing SQL script in server
ERROR: Error 1215: Cannot add foreign key constraint
SQL Code:
-- -----------------------------------------------------
-- Table `inver`.`sensors_has_greenhouse`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `inver`.`sensors_has_greenhouse` (
`sensors_entityId` VARCHAR(45) NOT NULL,
`greenhouse_fiwareServicePath` VARCHAR(45) NOT NULL,
PRIMARY KEY (`greenhouse_fiwareServicePath`, `sensors_entityId`),
INDEX `fk_sensors_has_greenhouse_greenhouse1_idx` (`greenhouse_fiwareServicePath` ASC),
INDEX `fk_sensors_has_greenhouse_sensors1_idx` (`sensors_entityId` ASC),
CONSTRAINT `fk_sensors_has_greenhouse_sensors1`
FOREIGN KEY (`sensors_entityId`)
REFERENCES `inver`.`sensors` (`entityId`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_sensors_has_greenhouse_greenhouse1`
FOREIGN KEY (`greenhouse_fiwareServicePath`)
REFERENCES `inver`.`greenhouse` (`fiwareServicePath`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_spanish_ci
SQL script execution finished: statements: 8 succeeded, 1 failed
Fetching back view definitions in final form.
Nothing to fetch
错误是相关表没有相同的属性
COLLATE
。该文档对此进行了以下说明:
所以表格:
sensors
并在中sensors_has_greenhouse
具有以下内容:COLLATE
CREATE TABLE
但
sensors_has_greenhouse
它与table有关greenhouse
,它没有COLLATE = utf8_spanish_ci
。如果两个非二进制列(String 类型的列,例如
VARCHAR
)具有不同的 ,则它们不能参与表之间的关系COLLATE
。这正是您的情况。解决方案
要么你授予
COLLATE = utf8_spanish_ci
表greenhouse
(已经users
,因为否则你会在后两者之间遇到同样的问题),或者你COLLATE = utf8_spanish_ci
从拥有它的两个表中删除。我已经完成了更正这些细节的概念证明,但并没有给我带来错误:
如果还是失败了怎么办?
由于您之前一直在运行
CREATE TABLE
,因此在关系创建失败之前,可能已经创建了一些表。所以你有几种可能性。最简单的方法是,如果您的表是新表并且还没有数据,则在重新开始
DROP TABLE IF EXISTS ...nombre-de-tabla...
之前运行每个表中的一个。但是只运行一次,以防止使用正确的设置重新创建表。CREATE TABLE
您可以通过其他类型的查询(例如
ALTER TABLE
)或直接在 DBMS 的图形界面中修改 COLLATE。笔记:
通常,不建议使用 type 的列来关联表
VARCHAR
。为此,您必须非常确定该值唯一地代表每条记录。他们还必须评估这可能带来的数据库性能成本。始终使用带有数字标识符的关系,它在对 NM 表中的数据进行排序时要好得多。是的,这是可能的,正如您被告知的那样,但这不是最推荐的,除了它没有太多逻辑之外,因为您希望当您看到该表时有数据的逻辑顺序,您可以通过使用将两个外键组合在一起的 ID 对该关系进行排序来实现这一点。
我在 NM 表周围的一个简单示例: