不能对 mysqli 使用多个 STMT 查询
Can't use more than one STMT query for mysqli
我正在尝试生成用户创建页面并进行验证以确定用户是否已经存在,为此我使用下一个代码:
在这里我将用户和他的密码插入 table USERS
mysqli_stmt_bind_param($guardar_usuario, 'ss', $usuario,$encriptar);
mysqli_stmt_execute($guardar_usuario);
这里我重用变量 $user 来恢复新创建的 id 用户
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = '$usuario' ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);
我将额外的数据插入到名为 PERSONAS
的 table
$guardar_persona = mysqli_prepare($connect, "INSERT INTO persona (id_usuario, nombre, email) VALUES (?, ?, ?)");
mysqli_stmt_bind_param($guardar_persona, 'iss', $ultimo_registro, $nombre_usuario, $email_usuario);
mysqli_stmt_execute($guardar_persona);
我的问题是第二个查询,数据插入到 table PERSONAS 不起作用,但是如果我删除第一个查询,它使插入到 table USERS,这个查询工作完美,所以我不知道是否有规则可以使这项工作正常进行?
抱歉,如果这是一个新手问题,我才开始以这种方式工作,以尽可能地防止数据输入。
执行准备好的语句时,mysqli 默认使用无缓冲查询。这是一个非常令人困惑的行为,但这意味着结果不会自动发送到 PHP。 MySQL 服务器将结果存储在服务器上并等待 PHP 检索它们。只要还有更多的结果要获取,就不能执行另一个查询。
要解决此问题,您需要调用 mysqli_stmt_store_result()
或获取所有结果。
在您的情况下,简单的选择是添加 store_result
并完成它。
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_bind_param($ultimo_registro, 's', $usuario);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_store_result($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);
但是,如果您停止直接使用 mysqli 函数,对您来说会容易得多。即使是一个简单的包装函数也可以帮助您避免所有这些 mysqli 混乱。
function safeQuery(mysqli $db, string $sql, array $params = []): ?array {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
然后您可以将整个准备好的语句抽象为一行代码:
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$result = safeQuery($connect, $consulta, [$usuario]);
if ($result) {
$id_usuario_creado = $result[0]['id_usuario'];
}
您甚至可以编写第二个函数,它只从准备好的语句中获取单个值。
function fetchSingle(mysqli $db, string $sql, array $params = []) {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_row()[0];
}
return null;
}
当您只想获取单个值时,这可以与 LIMIT 1
一起使用。
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$id_usuario_creado = fetchSingle($connect, $consulta, [$usuario]);
我正在尝试生成用户创建页面并进行验证以确定用户是否已经存在,为此我使用下一个代码:
在这里我将用户和他的密码插入 table USERS
mysqli_stmt_bind_param($guardar_usuario, 'ss', $usuario,$encriptar);
mysqli_stmt_execute($guardar_usuario);
这里我重用变量 $user 来恢复新创建的 id 用户
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = '$usuario' ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);
我将额外的数据插入到名为 PERSONAS
的 table$guardar_persona = mysqli_prepare($connect, "INSERT INTO persona (id_usuario, nombre, email) VALUES (?, ?, ?)");
mysqli_stmt_bind_param($guardar_persona, 'iss', $ultimo_registro, $nombre_usuario, $email_usuario);
mysqli_stmt_execute($guardar_persona);
我的问题是第二个查询,数据插入到 table PERSONAS 不起作用,但是如果我删除第一个查询,它使插入到 table USERS,这个查询工作完美,所以我不知道是否有规则可以使这项工作正常进行?
抱歉,如果这是一个新手问题,我才开始以这种方式工作,以尽可能地防止数据输入。
执行准备好的语句时,mysqli 默认使用无缓冲查询。这是一个非常令人困惑的行为,但这意味着结果不会自动发送到 PHP。 MySQL 服务器将结果存储在服务器上并等待 PHP 检索它们。只要还有更多的结果要获取,就不能执行另一个查询。
要解决此问题,您需要调用 mysqli_stmt_store_result()
或获取所有结果。
在您的情况下,简单的选择是添加 store_result
并完成它。
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_bind_param($ultimo_registro, 's', $usuario);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_store_result($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);
但是,如果您停止直接使用 mysqli 函数,对您来说会容易得多。即使是一个简单的包装函数也可以帮助您避免所有这些 mysqli 混乱。
function safeQuery(mysqli $db, string $sql, array $params = []): ?array {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
然后您可以将整个准备好的语句抽象为一行代码:
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$result = safeQuery($connect, $consulta, [$usuario]);
if ($result) {
$id_usuario_creado = $result[0]['id_usuario'];
}
您甚至可以编写第二个函数,它只从准备好的语句中获取单个值。
function fetchSingle(mysqli $db, string $sql, array $params = []) {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_row()[0];
}
return null;
}
当您只想获取单个值时,这可以与 LIMIT 1
一起使用。
$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$id_usuario_creado = fetchSingle($connect, $consulta, [$usuario]);