当前位置: 首页 > 面试题库 >

MySQL:添加约束(如果不存在)

花欣然
2023-03-14
问题内容

在我的数据库创建脚本中,创建脚本如下所示:

CREATE TABLE IF NOT EXISTS `rabbits`
(
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL,
    `main_page_id` INT UNSIGNED COMMENT 'What page is the main one',
    PRIMARY KEY (`id`),
    KEY `main_page_id` (`main_page_id`)
)
ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `rabbit_pages`
(
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `rabbit_id` INT UNSIGNED NOT NULL,
    `title` VARCHAR(255) NOT NULL,
    `content` TEXT NOT NULL,
    PRIMARY KEY (`id`),
    KEY `rabbit_id` (`rabbit_id`),
    CONSTRAINT `fk_rabbits_pages` FOREIGN KEY (`rabbit_id`) REFERENCES `rabbits` (`id`)
)
ENGINE=InnoDB;

ALTER TABLE `rabbits`
    ADD CONSTRAINT `fk_rabbits_main_page` FOREIGN KEY (`main_page_id`) REFERENCES `rabbit_pages` (`id`);

第一次运行良好,但是如果我再次运行,它将在最后一行失败,并带有“写入或更新时复制密钥”。

有什么办法可以做类似的ADD CONSTRAINT IF NOT EXISTS事情吗?就像我可以使用CREATE TABLE查询吗?


问题答案:

有趣的问题。您可能需要在调用CREATE TABLE语句之前禁用外键,然后再启用它们。这将允许您直接在CREATE TABLEDDL中定义外键:

例:

SET FOREIGN_KEY_CHECKS = 0;
Query OK, 0 rows affected (0.00 sec)

CREATE TABLE IF NOT EXISTS `rabbits` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL,
    `main_page_id` INT UNSIGNED COMMENT 'What page is the main one',
    PRIMARY KEY (`id`),
    KEY `main_page_id` (`main_page_id`),
    CONSTRAINT `fk_rabbits_main_page` FOREIGN KEY (`main_page_id`) REFERENCES `rabbit_pages` (`id`)
) ENGINE=InnoDB;
Query OK, 0 rows affected (0.04 sec)

CREATE TABLE IF NOT EXISTS `rabbit_pages` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `rabbit_id` INT UNSIGNED NOT NULL,
    `title` VARCHAR(255) NOT NULL,
    `content` TEXT NOT NULL,
    PRIMARY KEY (`id`),
    KEY `rabbit_id` (`rabbit_id`),
    CONSTRAINT `fk_rabbits_pages` FOREIGN KEY (`rabbit_id`) REFERENCES `rabbits` (`id`)
) ENGINE=InnoDB;
Query OK, 0 rows affected (0.16 sec)

SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.00 sec)

测试用例:

INSERT INTO rabbits (name, main_page_id) VALUES ('bobby', NULL);
Query OK, 1 row affected (0.02 sec)

INSERT INTO rabbit_pages (rabbit_id, title, content) VALUES (1, 'My Main Page', 'Hello');
Query OK, 1 row affected (0.00 sec)

SELECT * FROM rabbits;
+----+-------+--------------+
| id | name  | main_page_id |
+----+-------+--------------+
|  1 | bobby | NULL         |
+----+-------+--------------+
1 row in set (0.00 sec)

SELECT * FROM rabbit_pages;
+----+-----------+--------------+---------+
| id | rabbit_id | title        | content |
+----+-----------+--------------+---------+
|  1 |         1 | My Main Page | Hello   |
+----+-----------+--------------+---------+
1 row in set (0.00 sec)

UPDATE rabbits SET main_page_id = 2 WHERE id = 1;
ERROR 1452 (23000): A foreign key constraint fails

UPDATE rabbits SET main_page_id = 1 WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

UPDATE rabbit_pages SET rabbit_id = 2 WHERE id = 1;
ERROR 1452 (23000): A foreign key constraint fails


 类似资料:
  • 问题内容: Postgres是否有任何办法说如果约束已经存在,它将忽略该命令,从而不会引发错误? 问题答案: 这可能有所帮助,尽管可能有点脏: 然后致电: 更新: 根据Webmut的以下建议: 在您的开发数据库中,或者在您知道可以关闭依赖该数据库的应用程序作为维护时段的情况下,这可能很好。 但是,如果这是一个至关重要的24x7全天候生产环境,那么您真的不想像这样随意地放弃约束。即使是几毫秒,也有一

  • 问题内容: 我看了很多例子。但是此查询不起作用,出现以下错误: 错误1064(42000):您的SQL语法有错误;在第1行的’IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =’)附近,查看与您的MySQL服务器版本相对应的手册以使用正确的语法。 问题答案: 您可以为查询创建一个过程,

  • 问题内容: 我发现创建一个查询有困难。假设我有一个“产品和品牌”表。我可以使用此命令添加外键, 但是,如果外键不存在,我只需要运行此命令。我需要类似的事情是在不使用名称的情况下删除“外键约束”(如果存在)。 问题答案: 首先,您应该始终命名您的FK以及所有其他约束,以免出现此类麻烦。 但是,如果您不知道FK的名称,则可以使用多个系统视图进行检查:

  • 问题内容: 因此,我作为项目需求试图将外键约束添加到数据库中,并且它第一次或在两个不同的表上运行,但是在尝试添加外键约束时,我在两个表上遇到错误。我收到的错误消息是: 错误1215(HY000):无法添加外键约束 这是我用来创建表的SQL,两个有问题的表是和。 问题答案: 要查找特定错误,请运行以下命令: 并查看该部分。 子列的数据类型必须与父列完全匹配。例如,由于是,也需要是,而不是。 另外,您

  • 问题内容: 有没有办法给已经存在的约束命名? 例如 : 在上面的查询中,我没有命名外键约束,因此在创建表之后,我可以为其命名,也可以在不删除列的情况下删除外键约束吗? 问题答案: 是的,您可以像这样重命名约束: 编辑:我忘记了第二个问题。是的,您可以删除约束而不删除列。如果您不知道约束的名称,则可以在表中找到它,如下所示:

  • 问题内容: 我的研究和实验还没有得到答案,所以我希望能有所帮助。 我正在修改一个应用程序的安装文件,该应用程序在以前的版本中没有我想立即添加的列。我不想手动添加列,而是要在安装文件中并且仅在表中不存在新列的情况下才添加。 该表如下创建: 如果我在create table语句下面添加以下内容,那么我不确定如果该列已经存在(可能已填充)会发生什么情况: 因此,我尝试了在某处找到的以下内容。这似乎不起作