【问题标题】:InnoDB foreign key difficulty?InnoDB 外键难度?
【发布时间】:2011-08-10 16:14:36
【问题描述】:

下面我有两张桌子

用户users_profiles

都是innoDB和排序规则:utf8_general_ci

它们如下:

用户

CREATE TABLE `users` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`status` char(10) NOT NULL,
`username` varchar(15) NOT NULL,
`email` varchar(50) NOT NULL,
`password` char(32) NOT NULL,
`reg_date` int(11) NOT NULL,
`ip` varchar(39) DEFAULT NULL,
PRIMARY KEY (`uid`),
UNIQUE KEY `username` (`username`,`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

users_profiles

CREATE TABLE `users_profiles` (
`uid` int(11) NOT NULL,
`first_name` varchar(40) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`gender` char(6) DEFAULT NULL,
`website` varchar(100) DEFAULT NULL,
`msn` varchar(60) DEFAULT NULL,
`aim` varchar(60) DEFAULT NULL,
`yim` varchar(60) DEFAULT NULL,
`twitter` varchar(15) DEFAULT NULL,
UNIQUE KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在 phpmyadmin 中创建表后,我在 users_profiles 表上创建了一个外键,下面的代码是 phpMyAdmin 创建的。

如下:

ALTER TABLE `users_profiles`
ADD CONSTRAINT `users_profiles_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE;

基本上 users_profiles.uid 是一个外键并引用 users.uid

在 phpMyAdmin 中,我转到 insert 并填写一些示例数据,使 uid 显然可以自动递增。当我在 users 表中插入一条记录后,我进入 users_profiles 表并注意到 users.uid 没有自动插入 users_profiles,

这正常吗?

原因是当某人在表单上注册时,他们将被要求输入用户名、电子邮件和密码,我在 php 中进行查询以将该数据插入 users 表中,我认为因为我有一个外键,它也会自动在 users_profiles 表中插入一行,其中包含用户表中的 uid,因此用户和那里的配置文件之间存在链接。但是当我在 users 表中插入一条记录时,users.uid 不会插入到 users_profiles 表中。

我尝试了另一个示例来看看会发生什么,由于更新和删除的级联,这个示例可以正常工作。

如果我在 users 表中插入一行,然后手动将 users.uid 插入 users_profiles.uid(它们现在已链接)并添加例如我的 first_name 和 last_name 然后在 phpmyadmin 中删除用户从 users 表中删除 users_profiles 表中的行。这显然应该像它一样工作,因为我不希望删除用户并保留配置文件。

这让我感到困惑,因为当我创建表单并且用户注册时,他们基本上没有个人资料,因为在注册时没有为他们创建个人资料,并且 user_profiles 表中有 users.uid(他们之间没有链接) 虽然我有一个外键。

能否解释一下为什么它没有按我的预期工作,也许它应该像我希望的那样工作,但是出了点问题,或者我错过了重点。


更新

参考@Mark Wilkins 的回复

我现在明白你的意思了。但我不能 100% 确定的是:

用户注册,在用户表中创建一条记录;他们登录并访问个人资料页面,可以在其中填写并提交表格。

在处理表单时,我是否认为我需要执行以下操作:

用户填写个人资料表格并提交(他们第一次提交个人资料,因为他们是新用户),在验证数据等之后,我首先检查用户表中的 uid 是否与 users_profile 表中的 uid 匹配,如果有匹配然后 UPDATE 记录与新值(这意味着用户之前已经填写了那里的配置文件,因为他们没有注册)但是如果在两个表中的 uid 上都没有找到匹配项,那么我将执行一个 INSERT 查询,因为没有用户的配置文件尚未存在。我认为显然我会将用户表中的 uid 与成功登录时的其他数据一起存储在会话中,并且会话中的 uid 将是插入到 uid 列中的 users_profiles 表中的 uid?这样就在两个表之间创建了一个链接,如果我现在决定删除用户,那里的个人资料也将被删除。

【问题讨论】:

    标签: php mysql database-design foreign-keys


    【解决方案1】:

    外键约束不是为创建行而设计的。它们的目的是通过强制子表中引用父表值的值实际存在于该父表中来确保数据完整性,并防止删除在子表中引用它的父行。

    在插入时,调用代码必须将行写入两个表(先是用户,然后是配置文件)。

    【讨论】:

    • 嗨@Thomas,我更新了原始帖子,也许你可以回复并告诉我我在更新中回复马克威尔金斯时所说的是否正确?谢谢phplover
    【解决方案2】:

    如果我正确地遵循了描述,它会按预期工作。外键关系基本上表示给定子级必须存在父级(在您的示例中,给定 user_profile 必须存在用户)。它不需要相反的情况(用户存在 user_profile 记录)。它永远不会导致对子表执行 INSERT。您必须将记录插入到 user_profile 表中,并且外键关系将保证它被维护。

    编辑以获取其他 OP 信息:一般来说,是的,我相信这是您想要做的事情。我对 Web 开发的处理还不够,无法知道该特定过程是否正确。但是,无论哪种情况(无论是否创建了个人资料记录),您都需要知道要修改哪个用户。但是,我对此的看法是在创建用户记录后直接创建关联的 user_profile 记录(只需将其中的信息字段留空)。这样你在去编辑它时就知道它存在,并且你不必执行 MERGE 样式操作。

    【讨论】:

    • 嗨@Mark Wilkins,我更新了原始帖子,因为这里没有足够的字符。如果您不介意回复让我知道我所说的是否正确。谢谢phplover
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2015-05-12
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    相关资源
    最近更新 更多