我正在寻找将数据插入多个MySQL表的最佳实践方法,其中一些列是外键依赖项.这是一个例子:
Table: contacts
--------------------------------------------------------------------
| contact_id | first_name | last_name | prof_id | zip_code |
--------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
'contacts'表有PRIMARY KEY(contact_id),它只是auto_increments,和FOREIGN KEY(prof_id)REFERENCES'专业'表,FOREIGN KEY(zip_code)REFERENCES'zip_code'表.这些表看起来像这样:
Table: profession
----------------------------
| prof_id | profession |
----------------------------
Run Code Online (Sandbox Code Playgroud)
其中'prof_id'是INT NOT NULL AUTO_INCREMENT PRIMARY KEY,和
Table: zip_code
--------------------------------
| zip_code | city | state |
--------------------------------
Run Code Online (Sandbox Code Playgroud)
其中'zip_code'是INT(5)NOT NULL PRIMARY KEY.
我有一个新人想要添加记录,让我们说:
first_name = 'John', last_name = 'Doe', profession = 'Network Administrator', city = 'Sometown', state = 'NY', zip_code = 12345
Run Code Online (Sandbox Code Playgroud)
这是我正在尝试做的事情:我想获取该信息并将其插入适当的表和列中.为了防止列中的重复值(例如专业),我首先要确保没有"网络管理员"的条目,如果有,我只想获取其键值,如果不插入它然后获取其键值.对于zip_code,city,state也是如此 - 如果它存在则只使用该zip_code键,否则插入新数据并获取相关密钥.然后,最后,我想使用提供的信息输入新联系人到'联系'表,包括与专业和位置相关的其他表中的相应键值.
我的问题是,推荐的最佳方法是什么?我知道我可以坐在这里写单个陈述以检查给定的职业是否存在,如果不存在则输入,然后获取密钥.为zip_code做同样的事情.然后最后将所有这些插入到联系人中,但是我知道必须有更好的方法来在更少(可能是一个)语句中完成此操作,特别是考虑到这可能会导致问题,例如,如果数据库在中间离线了一会儿所有这一切.有没有办法在这个INSERT中使用JOIN来基本上将所有内容级联到正确的位置?我应该用TRANSACTION系列语句来处理这个问题吗?
我正处于使用SQL的学习阶段,但我觉得到目前为止我使用的书籍和资源有点跳跃到使用嵌套查询和JOINS,假设我们已经填充了所有这些数据表.我甚至乐于接受关于我应该谷歌搜索什么以获得更好的知识的建议,或任何有助于填补这一空白的资源.理想情况下,我希望看到一些功能正常的SQL代码来做到这一点.如果需要,假设PHP作为与数据库交互的语言,但命令行sql是我的目标.提前谢谢,希望我把一切都清楚了.
简而言之,您想要使用事务 (更多关于此的文档),以便您的插入是原子的。这是保证插入所有(或没有)数据的唯一方法。否则,您可能会遇到您所描述的情况,即在某些插入后数据库变得不可用,而其他插入则无法完成。事务告诉数据库您正在做的事情是全有或全无,因此如果出现问题,它应该回滚。
当您使用合成主键时,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;
Run Code Online (Sandbox Code Playgroud)