mysql 外键不能关联到一自增的字段么?

渔樵耕读 发布于 2013/09/03 23:15
阅读 2K+
收藏 0

我是用django。

先是建立了表A  主键Aid 自增

然后建立表B  主键Bid 自增  外键Aid

构建表结构的时候 报错 说:

error 1075 42000 incorrect table definition there can be only one auto column and it must be defined as a key


我该咋解决呢。。。

加载中
0
晴风晓月
晴风晓月
关键问题是出在ForeignKey上,因为我们自定义了BigIntegerAutoField,将其数据类型设为了bigint AUTO_INCREMENT,在建立外键里,默认情况下这个数据类型也会直接返回,因此造成了tucao_reply表里有了两个自增的字段,这是mysql不允许的。因此我们就需要改变这种默认的逻辑,而参考系统中ForeignKey的实现,发现系统其实对于AutoField也是做了特殊处理的,相关代码可以参考Django的源代码,因此我也就照着这样的方式,扩展了ForeignKey,生成的SQL语句就没有问题了
晴风晓月
晴风晓月
回复 @渔樵耕读 : 总体来说,我觉得Django还是非常不错的,如果她还有些不完善,那我们也应该让她完善起来
渔樵耕读
渔樵耕读
懂了。唉 django 还是不太完善啊。
0
开源中国董事会主席
开源中国董事会主席
当然可以啊 必须得是索引
0
ccdos
ccdos
主键Bid 没必要自增了吧,你都 外键 连到 aid 了
0
卖切糕大叔
卖切糕大叔
外键肯定是可以自增的,这肯定是你的表结构写错了。你检查下你建数据的语句,大概忘了把自增字段设成主键了,也可能你在同一个表内多定义了一个自增字段。
渔樵耕读
渔樵耕读
确实是一个表里两个自增字段了。 一个是主键,一个是外键 链接到另一个表里的主键
0
晴风晓月
晴风晓月
取消B表中的外键aid的自增属性就没问题了,提示已经说得很清楚了嘛
0
晴风晓月
晴风晓月
Django的话最好上代码,我还没有遇到过这样的情况
渔樵耕读
渔樵耕读
代码贴上了。 请注意TucaoReply 中的 tcId~
0
渔樵耕读
渔樵耕读
from django.db import models
from fields import BigIntegerAutoField

#python manage.py schemamigration author add_mobile_column --auto 执行model 修改 同步db的命令
#python manage.py migrate  提交 同步db
class Tucao(models.Model):
    tcId = BigIntegerAutoField(primary_key=True,max_length=20,db_column='tucao_id',help_text='主键')
    tcUserId = models.BigIntegerField(blank=False,max_length=11,db_column='tucao_account_id',help_text='吐嘈者帐户id,未登录者为-1')
    tcAccountName = models.CharField(max_length=50,blank=False,db_column='tucao_account_name',help_text='吐嘈者昵称,匿名显示ip')
    tcAccountEmail = models.EmailField(max_length=50,blank=False,db_column='tucao_account_email',help_text='吐嘈者email')
    tcContext = models.TextField(max_length=160,blank=False,db_column='tucao_context',help_text='吐嘈内容')
    tcPic = models.CharField(max_length=1000,blank=True,db_column='tucao_pic',help_text='吐槽图片链接')
    class Meta:
        db_table = 'tucao'
        verbose_name = '吐槽表'

class TucaoReply(models.Model):
    tcReplyId = BigIntegerAutoField(primary_key=True,max_length=19,db_column='tucao_reply_id',help_text='回复主键')
    tcId = models.ForeignKey(Tucao,db_column='tucao_id',blank=True, null=True)
    tcReplyAccountId = models.BigIntegerField(blank=False,max_length=11,db_column='tucao_reply_account_id',help_text='回复者帐户id,未登录为-1')
    tcReplyAccountName = models.CharField(max_length=50,db_column='tucao_reply_account_name',blank=False,help_text='回复者昵称,匿名的话记录IP')
    tcReplyAccountEmail = models.EmailField(max_length=50,db_column='tucao_reply_account_email',blank=False,help_text='如果未登录回复,需要记录邮箱')
    tcReplyContext = models.TextField(max_length=160,blank=False,db_column='tucao_reply_context',help_text='回复内容')
    tcReplyDate = models.DateTimeField(db_column='tucao_replay_datetime',help_text='回复时间')
    class Meta:
        db_table = 'tucao_reply'
        verbose_name = '吐槽回复表'
渔樵耕读
渔樵耕读
回复 @晴风晓月 : 把这个类型 换成BigInteger也会报错。。。 奇了怪了。
晴风晓月
晴风晓月
回复 @渔樵耕读 : 你这个BigIntegerAutoField应该是你自己扩展的吧,我在Django的文档里没有找到,你看一下扩展有没有问题呢?
渔樵耕读
渔樵耕读
回复 @晴风晓月 : BigIntegerAutoField 只是想让BigInt类型的主键自增。
晴风晓月
晴风晓月
回复 @渔樵耕读 : 应该是BigIntegerAutoField有问题
渔樵耕读
渔樵耕读
回复 @晴风晓月 : 难道外键不能指定字段名???
下一页
0
晴风晓月
晴风晓月

我想我已经把问题解决了。

首先我自己将实现的BigIntegerAutoField如下所示:

class BigIntegerAutoField(models.BigIntegerField):
    def db_type(self, connection):
        if 'mysql' in connection.__class__.__module__:
            return 'bigint AUTO_INCREMENT'
        return super(BigIntegerAutoField, self).db_type(connection)


由于改变了相应的数据类型,因此改写ForeignKey为如下代码:

class BigIntegerForeignKey(models.ForeignKey):
    def __init__(self, to, to_field=None, **kwargs):
        super(BigIntegerForeignKey, self).__init__(to, **kwargs)
 
     def db_type(self, connection):
         rel_field = self.rel.get_related_field()
         if isinstance(rel_field, BigIntegerAutoField):
             return models.BigIntegerField().db_type(connection=connection)
         return rel_field.db_type(connection=connection)

然后将第19行代码改写如下:

tcId = BigIntegerForeignKey(Tucao,db_column='tucao_id',blank=True, null=True)

这样就没有问题了。


渔樵耕读
渔樵耕读
3Q~~~ 还帮我写了代码。 不过我想弄清楚。 我之前那么写为什么不行呢。 我的BigIntegerAutoField 的代码就是按照你那么写的。
伊藤熊吉
伊藤熊吉
最佳答案 好评
0
伊藤熊吉
伊藤熊吉

嘛,这个应该是数据库设计上的失误啊....
回复表里加上一个回复的tucao的id?

渔樵耕读
渔樵耕读
回复 @伊藤熊吉 : 应该是回复表 增加一个字段 作为外键 关联 吐槽表~ 我寻思自己加上就得了。。没跟你说。。
伊藤熊吉
伊藤熊吉
回复 @渔樵耕读 : 确实是我设计上的失误,看邮件,你看看,如果没问题的话我就改
渔樵耕读
渔樵耕读
没有失误啊! 吐槽-回复 是1-N的关系啊。 所以回复表里肯定会吐槽的外键啊。 不然怎么找到回复是属于哪一个吐槽里的信息。
返回顶部
顶部