如何将数据插入到涉及外键依赖项的多个表中(MySQL)

时间:2013-08-05 22:50:18

标签: php mysql sql

我正在寻找将数据插入多个MySQL表的最佳实践方法,其中一些列是外键依赖项。这是一个例子:

Table: contacts
--------------------------------------------------------------------
|  contact_id  |  first_name  | last_name  |  prof_id  |  zip_code  |
--------------------------------------------------------------------

'contacts'表有PRIMARY KEY(contact_id),它只是auto_increments,FOREIGN KEY(prof_id)REFERENCES'professional'表,FOREIGN KEY(zip_code)REFERENCES'zip_code'表。这些表看起来像这样:

Table: profession
----------------------------
|  prof_id  |  profession  |
----------------------------

其中'prof_id'是INT NOT NULL AUTO_INCREMENT PRIMARY KEY,和

Table: zip_code
--------------------------------
|  zip_code  | city  |  state  |
--------------------------------

其中'zip_code'是INT(5)NOT NULL PRIMARY KEY。

我有一个新人想要添加记录,让我们说:

first_name = 'John', last_name = 'Doe', profession = 'Network Administrator', city = 'Sometown', state = 'NY', zip_code = 12345

以下是我要做的事情:我想获取该信息并将其插入相应的表和列中。为了防止列中的重复值(例如专业),我首先要确保没有“网络管理员”的条目,如果有,我只想获取其键值,如果不插入它然后获取其键值。对于zip_code,city,state也是如此 - 如果它存在则只使用该zip_code键,否则插入新数据并获取相关密钥。然后,最后,我想使用提供的信息将新联系人输入“联系人”表,包括与职业和位置相关的适当关键值。

我的问题是,推荐的最佳方法是什么?我知道我可以坐在这里写单个陈述以检查给定的职业是否存在,如果不存在则输入,然后获取密钥。为zip_code做同样的事情。然后最后将所有这些插入到联系人中,但是我知道必须有更好的方法来在更少(可能是一个)语句中完成此操作,特别是考虑到这可能会导致问题,例如,如果数据库在中间离线了一会儿所有这一切。有没有办法在这个INSERT中使用JOIN来基本上将所有内容级联到正确的位置?我应该用TRANSACTION系列语句来处理这个问题吗?

我正在使用SQL进入学习阶段,但我觉得到目前为止我使用的书籍和资源已经跳过使用嵌套查询和JOINS,假设我们已经填充了所有这些数据表。我甚至乐于接受关于我应该谷歌搜索什么以获得更好的知识的建议,或任何有助于填补这一空白的资源。理想情况下,我希望看到一些功能正常的SQL代码来做到这一点。如果需要,假设PHP作为与数据库交互的语言,但命令行sql是我的目标。提前谢谢,希望我把一切都搞清楚了。

1 个答案:

答案 0 :(得分:4)

简而言之,您希望使用transactions (more doc on this),以便您的插入内容为atomic。这是保证插入所有(或没有)数据的唯一方法。否则,您可以进入您描述的情况,在某些插入后数据库变得不可用而其他数据库无法完成。事务告诉数据库你正在做什么是全有或全无,所以如果出现问题它应该回滚。

当您使用合成主键时,PHP和其他语言提供了获取最后插入ID的机制。如果您想完全在MySQL中完成,可以使用LAST_INSERT_ID()函数。你最终会得到这样的代码:

START TRANSACTION;
INSERT INTO foo (auto,text)
    VALUES(NULL,'text');         # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
    VALUES(LAST_INSERT_ID(),'text');  # use ID in second table
COMMIT;