简体   繁体   English

InnoDB外键难点?

[英]InnoDB foreign key difficulty?

Below I have two tables 下面我有两个表

users and users_profiles 用户users_profiles

Both are innoDB and collation: utf8_general_ci 两者都是innoDB和归类:utf8_general_ci

They are as follows: 它们如下:

users 用户

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 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;

After creating the tables in phpmyadmin I created a foreign key on the users_profiles table, code below is what phpMyAdmin created. 在phpmyadmin中创建表后,我在users_profiles表上创建了一个外键,以下代码是phpMyAdmin创建的。

As follows: 如下:

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

basically the users_profiles.uid is a foreign key and references the users.uid 基本上,users_profiles.uid是一个外键,并引用了users.uid

In phpMyAdmin I go to insert and fill in some sample data leaving the uid obviously to auto increment. 在phpMyAdmin中,我要插入并填写一些示例数据,而使uid显然要自动递增。 When i have inserted a record in users table I goes into the users_profiles table and notice the users.uid is not inserted automatically in the users_profiles, 当我在用户表中插入一条记录时,我进入了users_profiles表,并注意到users.uid没有自动插入到users_profiles中,

Is this normal? 这是正常的吗?

Reason is when someone for example registers on a form, they will be asked for username, email and password, and i do a query in php to insert that data into users table, i thought that because i have a foreign key that it would also automatically insert a row in the users_profiles table with the uid from users table so there is a link between the user and there profile. 原因是,例如有人在表格上注册时,系统会要求他们输入用户名,电子邮件和密码,而我在php中进行查询以将该数据插入到用户表中,我认为因为我有一个外键,所以自动在users_profiles表中插入带有来自users表的uid的行,以便在用户和个人资料之间存在链接。 But when i insert a record into users table the users.uid is not inserted into the users_profiles table. 但是当我在用户表中插入一条记录时,users.uid并没有插入到users_profiles表中。

I tried another example to see what would happen and this one works as i would expect due to the cascade on update and delete. 我尝试了另一个示例以查看会发生什么,并且由于更新和删除的级联,该示例可以按我的预期工作。

If i insert a row in users table and then manually insert the users.uid into users_profiles.uid (they are now linked) and add for example my first_name and last_name then in phpmyadmin delete the user from users table it deletes the row in the users_profiles table. 如果我在用户表中插入一行,然后手动将users.uid插入users_profiles.uid(它们现在已链接)并添加例如first_name和last_name,然后在phpmyadmin中从users表中删除用户,则会删除users_profiles中的行表。 This works like it should obviously as i don't want a user to be deleted and have there profile remain. 这显然应该工作,因为我不希望删除用户并保留个人资料。

This has confused me as when I do create a form and a user signs up, they essentially would not have a profile because on signup no profile is created for them with there users.uid in the user_profiles table (no link between them) although I have a foreign key. 这让我感到困惑,因为当我创建表单并进行用户注册时,他们基本上没有配置文件,因为在注册时没有为用户创建任何配置文件,user_profiles表中没有user.uid(他们之间没有链接),尽管我有一个外键。

Can some explain why it's not working as I expect, maybe it should be working like I want it to but something is wrong or I am missing the whole point otherwise. 有人可以解释为什么它没有按我预期的那样工作,也许它应该像我想要的那样工作,但是出了点问题,否则我会遗漏整个要点。


UPDATE UPDATE

In reference to reply from @Mark Wilkins 引用@Mark Wilkins的回复

I understand what you mean now. 我明白你的意思了。 But something I am not 100% sure on is this: 但是我不确定100%是这样的:

User signs up, a record is created in users table; 用户注册,在用户表中创建一条记录; they login and visit profile page where the can fill it in and submit the form. 他们登录并访问个人资料页面,可以在其中填写并提交表格。

On processing the form am I right in thinking I would need to do the following: 在处理表格时,我认为我将需要执行以下操作:

user filled in profile form and submitted (first time they submitted profile as they are a new user), after validating data etc I first check to see if the uid in the users table match a uid in the users_profile table, if there's a match then UPDATE record with new values (this would mean the user has previously filled in there profile as on signup they don't have one) but if no match is found on uid from both tables then I would perform an INSERT query because no profile yet exists for the user. 用户填写个人资料表格并提交(他们是新用户时首次提交个人资料),在验证数据等之后,我首先检查users表中的uid是否与users_profile表中的uid匹配,如果存在匹配项,则具有新值的UPDATE记录(这意味着用户以前已经在那里填写了配置文件,因为他们没有注册),但是如果在两个表的uid上都找不到匹配项,那么我将执行INSERT查询,因为尚无配置文件为用户。 I take it that obviously I would store the uid from users table in session with other data on successful login and the uid in session would be the uid that is inserted into the users_profiles table in column uid? 我认为显然我会在成功登录后将用户表中的uid与其他数据存储在一起,并且成功登录时的uid将是插入到列uid的users_profiles表中的uid? That way a link is created between two tables and if I now decide to delete the user there profile will also be deleted to. 这样,将在两个表之间创建链接,如果我现在决定删除该用户,那里的配置文件也将被删除。

Foreign key constraints are not designed to create rows. 外键约束不是设计用来创建行的。 Their purpose is to ensure data integrity by forcing that a value in a child table that references a parent table value actually exists in that parent table and prevents a parent row from being deleted that has references to it in a child table. 它们的目的是通过强制在子表中引用父表值的值实际上存在于该父表中,并防止删除在子表中具有对其引用的父行来确保数据完整性。

On insert, the calling code must write rows into the two tables (first users then profiles). 插入时,调用代码必须将行写入两个表(首先是用户,然后是配置文件)。

If I followed the description correctly, it is working as expected. 如果我正确地遵循了说明,则它可以按预期运行。 A foreign key relationship basically says that a parent must exist for a given child (a user must exist for a given user_profile in your example). 外键关系从根本上说,给定的孩子必须有一个父母(在您的示例中,给定的user_profile必须有一个用户)。 It does not require the opposite (that a user_profile record exist for a user). 不需要相反的操作(用户存在user_profile记录)。 It will never result in an INSERT being performed on the child table. 它永远不会导致在子表上执行INSERT。 You have to insert the record into the user_profile table and the foreign key relationship will guarantee that it is maintained. 您必须将记录插入到user_profile表中,并且外键关系将保证对其进行维护。

Edit for the additional OP info: In general, yes I believe that is the thing you want to do. 编辑其他OP信息:通常,是的,我相信这是您想要做的事情。 I have not dealt enough with web development to know if that particular process is correct. 我对Web开发的处理还不够,无法知道该特定过程是否正确。 In either case, though (whether or not a profile record has been created), you will need to know which user to modify. 但是,无论哪种情况(无论是否创建了个人档案记录),您都需要知道要修改哪个用户。 My opinion about this, however, would be to create the associated user_profile record directly after creating the user record (just leave the informational fields empty in it). 但是,我对此的看法是在创建用户记录后立即创建关联的user_profile记录(只需在其中保留信息字段为空)。 That way you know it exists when the go to edit it and you don't have to perform a MERGE style operation. 这样一来,您便可以知道在编辑时它的存在,而不必执行MERGE样式的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM