我有3个表,我必须在注册新用户后向他们添加记录:
表格列表:
予。的用户
...... ...... id(auto_increment,primary)
...... ......电子邮件(新用户的电子邮件地址)
II。的博客
...... ...... id(auto_increment,primary)
... ... ... owner_id(=' id' in' users')
III。的事件
...... ...... id(auto_increment,primary)
... ... ... owner_id(=' id' in' users')
... ... ... blog_id(=' id' in' blogs')
在这种情况下,我找到了2个添加顺序记录的解决方案:
解决方案1:使用lastInsertId
<?php
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
解决方案2:使用单execute()
<?php
try {
// Step 1
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email);" .
"INSERT INTO blogs (owner_id) VALUES ((SELECT id FROM users WHERE email = :email));" .
"INSERT INTO events (owner_id, blog_id) VALUES ((SELECT id FROM users WHERE email = :email), (SELECT id FROM blogs WHERE owner_id = (SELECT id FROM users WHERE email = :email)));");
$query->bindParam(':email', $email);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
我应该选择哪种解决方案以获得更好的性能和安全性?为我的目的有更好的解决方案吗?
注意:使用PDO
创建的连接:
<?php
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
try {
$conn = new PDO("mysql:host=" . App::DB_HOST . ";dbname=" . App::DB_NAME . ";charset=utf8", App::DB_USERNAME, App::DB_PASSWORD, $options);
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
答案 0 :(得分:3)
我会使用交易作为第一选项的修改。
$conn->beginTransaction();
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
$conn->commit();
}
catch (PDOException $e) {
// roll back transaction
$conn->rollback();
echo $e->getMessage();
die();
}
答案 1 :(得分:0)
编辑。我一开始误解了这个问题,认为你使用的是exec(),而不是执行()。
所以,实际上你可以将两者结合起来,因为lastInsertId只是Mysql的LAST_INSERT_ID()的PHP包装器 但是,由于您需要两个ID,因此设置变量需要额外的混乱。因此,我怀疑第二种选择是否值得,尽管可行。 请注意,仅当PDO仿真模式关闭时,第二个才会起作用
肯定没有像“表演”这样的问题。两者都会完美无缺。
答案 2 :(得分:0)
如果你做了一些基准测试,你会发现大部分时间都会丢失。 从像这样的简单查询的个人基准测试来看,执行时间非常短。 真正花费时间的唯一事情是初始化/准备功能。
制作3个请求会比创建一个大请求慢。
编辑:
选项1是正确的选项,因为你确实需要使用id,不使用字符串链接或其他东西使用id's。
来自那个(准备好的)大查询的公寓比3x准备好。