MySQL 数据库中指定的两个主键

Posted

技术标签:

【中文标题】MySQL 数据库中指定的两个主键【英文标题】:Two primary keys specified in MySQL database 【发布时间】:2011-10-08 22:42:25 【问题描述】:

我正在尝试创建一个作为现有数据库副本的测试数据库。我正在使用 Django 模型(理论上是与原始数据库一起使用的模型)来执行此操作。我最近从其他人那里继承了代码,并试图弄清楚代码到底发生了什么。

在模型中,其中一个表有两列被标识为主键。

        column1 = models.IntegerField(primary_key = True)
        column2 = models.IntegerField(primary_key = True)
        column3 = models.CharField(max_length = 30)

当我尝试将此模型同步到测试数据库时 - 发生错误:

文件“/somePathHere/mysqldb/connections.py”,第 36 行,在默认错误处理程序中引发错误类,错误值 _mysql_exceptions.OperationalError: (1068, '多个主键定义')

django docs 中写到 Django 不允许多个主键。但是,查看原始 MySQL 数据库中DESCRIBE [tablename] 的输出,似乎这正是这里发生的事情:

        +------------+------------+------+-----+---------+-------+
        | Field      | Type       | Null | Key | Default | Extra |
        +------------+------------+------+-----+---------+-------+
        | IDENTIFIER | bigint(20) | NO   | PRI | NULL    |       |
        | TIMESTAMP_ | bigint(20) | NO   | PRI | NULL    |       |
        | VALUE_     | longtext   | YES  |     | NULL    |       |
        +------------+------------+------+-----+---------+-------+

请注意,IDENTIFIER 和 TIMESTAMP_ 都被列为主键。

我在 SO(Example 1、Example 2 和 Example 3)上看到了很多关于基于多列创建主键的主题 - 我看到的是复合键吗?在这种情况下,这是如何通过 Django 模型传递的,即如何复制它?

如果不是复合键,它是什么?

【问题讨论】:

【参考方案1】:

Django 不支持它,但有一个解决方法。在您的模型上指定 unique_together 和 Meta 部分中的字段:

class MyClass(models.Model):
    IDENTIFIER = models.IntegerField(blank=False,null=False)
    TIMESTAMP_ = models.IntegerField(blank=False,null=False)
    VALUE_ = models.TextField(blank=True, null=True)

    class Meta:
        unique_together = ('IDENTIFIER', 'TIMESTAMP_')

这将保留两列主键的行为。

【讨论】:

谢谢,这非常接近我的需要,只是,我注意到它导致 Django 创建自己的自动 ID 主键列,这是我不想要的。此外,列的详细信息被标记为“mul” - 这是正确的吗? Django 需要一个表上的主键,有什么特别的原因你绝对不能有一个吗?主键对您有何不利影响?是的,MySQL 只是让您知道该列已编入索引,并且它不是唯一的 (UNI) 或主 (PRI)。来自 MySQL 文档:“如果 Key 是 MUL,则允许在列中多次出现给定值。该列是非唯一索引或可以包含 NULL 值的唯一值索引的第一列。” 嗯,主键应该是标识符和时间戳的组合,而不是该表的自动 ID。使用 django 设置它自己的主键,我无法看到 unique_together 如何能够保留两列主键行为。如果 MUL 键可以是非唯一的或具有空值的唯一键,那么它如何用作主键? MUL 只关注列,而不关注两列的组合。您是否测试过尝试为两列插入重复值? 嗯,很有趣。我还没有。由于时间戳,数据库中的所有值无论如何都是唯一的。【参考方案2】:

Django 当前为does not support multi-column primary keys,尽管有一些补丁/分支对其进行了扩展(具有不同程度的抛光)。来自常见问题解答"Do Django models support multiple column primary keys?":

没有。仅支持单列主键。

但这在实践中不是问题,因为没有什么可以阻止您添加其他约束(使用unique_together model option 或直接在您的数据库中创建约束),并在该级别强制执行唯一性。管理界面等工作需要单列主键;例如,您需要一种能够指定要编辑或删除的对象的简单方法。

您看到的不是两个主键,而是一个两列主键。表根据定义只能有一个主键。

【讨论】:

【参考方案3】:

这是一个复合主键。尝试执行此操作:

show create table mytable;

它应该显示复合键的定义。

从 mysql 的角度来看,这并不是什么“不寻常的”。

【讨论】:

这对于查看组合键的定义方式非常有帮助。谢谢!

以上是关于MySQL 数据库中指定的两个主键的主要内容,如果未能解决你的问题,请参考以下文章

mysql 中用正则表达式如何取一个字符串中指定的字段,

如何在mysql中定时清除所有库中指定的表中的数据,而不用每个库都写一遍定时任务,求大神指点!!!

MySQL相关

Firebase 数据库从子节点 B 中指定的子节点 A 检索对象

[两个指针]删除字符串中指定的字符

为啥我的 Solidity 构造函数需要两个未在参数中指定的变量?