我有下面的代码,它可以正常工作并更新数组中包含的每个记录:

$check_list = isset($_POST['check_list']) ? $_POST['check_list'] : array();
foreach($check_list as $check_list) {
$query = "UPDATE `stock` SET `signature_id` = 0,
                              user_id = 0,
                             `status_id` = 1
            WHERE `id` = '$check_list'";
$result = mysqli_query($conn, $query);


现在,我需要它对数组中的每个结果执行多个查询,因此我已使用mysqli_multi_query将代码更改为以下代码:

$check_list = isset($_POST['check_list']) ? $_POST['check_list'] : array();
foreach($check_list as $check_list) {
    $query = "UPDATE `stock` SET `signature_id` = 0,
                                  user_id = 0,
                                 `status_id` = 1
                WHERE `id` = '$check_list';
               INSERT INTO `returned`
                        (`id`, `stock_id`, `signature_id`,
                        `user_id`, `timestamp`)
                VALUES ('','$check_list','$id',
                        '$user_id',now())";
    $result = mysqli_multi_query($conn, $query);


但是现在它只对数组中的第一条记录执行一个UPDATE和一个INSERT,而忽略其他的

最佳答案

由于可重用性和安全性,@ RiggsFolly会针对已准备好的参数化语句和事务提供最佳建议,但是如果您希望/需要使用mysqli_multi_query,(因为您不想在中间过渡到新的查询过程,项目或因为它对您而言没有吸引力),这是mysqli_multi_query为您服务的方式:

查询组合:

如果SET值保持相同,而只有id不同,则可以将所有UPDATE查询合并为一个查询。如果值是静态的,则可以使用implode();否则,可以选择在单个查询的SET子句中使用(详细/丑陋的)CASE语句,还是像在原始帖子中创建多个UPDATE查询之间进行选择。

$queries="UPDATE `stock` SET `signature_id`=0,`user_id`=0,`status_id`=1 WHERE `id` IN (".implode(',',$check_list).");";


与INSERT查询类似,它们都可以通过implode()或仅扩展VALUE部分的foreach循环合并为一个语句。

$queries.="INSERT INTO `returned` (`stock_id`,`signature_id`,`user_id`,`timestamp`) VALUES ('".implode("','$id','$user_id',now()),('",$check_list)."','$id','$user_id',now());";


要么

$queries.="INSERT INTO `returned` (`stock_id`,`signature_id`,`user_id`,`timestamp`) VALUES ";
foreach($check_list as $k=>$check_list){
    // manipulate $id and $user_id as needed
    $queries.=($k==0?"":",")."('$check_list','$id','$user_id',now())";
}


故障意识:

如果您不需要任何形式的成功指示,那么单线工作就可以了(将其置于任何循环之外):

mysqli_multi_query($conn,$queries)


否则,您将需要更大的代码块:

if(mysqli_multi_query($conn,$queries)){
    do{
        echo "<br>Rows = ",mysqli_affected_rows($conn);
    } while(mysqli_more_results($conn) && mysqli_next_result($conn));
}
if($mysqli_error=mysqli_error($conn)){
    echo "<br>Syntax Error: $mysqli_error";
}


我已经对两个查询使用implode()测试了我的解决方案,并成功使用了:

$check_list=array(1,3,5,6,10,11);


以及以下数据库的设置:

CREATE TABLE `stock` (
    id int(10) NOT NULL AUTO_INCREMENT,
    signature_id int(10) NOT NULL,
    user_id int(10) NOT NULL,
    status_id int(10) NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE `returned` (
    id int(10) NOT NULL AUTO_INCREMENT,
    stock_id int(10) NOT NULL,
    signature_id int(10) NOT NULL,
    user_id int(10) NOT NULL,
    `timestamp` datetime NOT NULL,
    PRIMARY KEY (id)
);

/* Declaring your `id` columns with AUTO_INCREMENT means you can omit them from your INSERT query. */
/* Depending on your mysql version, creating a default datetime for `timestamp` may be possible which then would permit omitting `timestamp` from your INSERT query too. */

INSERT INTO `stock` (`signature_id`,`user_id`,`status_id`) VALUES
    (1,1,1),
    (2,2,2),
    (3,3,3),
    (4,4,4),
    (5,5,5),
    (6,6,6),
    (7,7,7),
    (8,8,8),
    (9,9,9),
    (10,10,10),
    (11,11,11),
    (12,12,12);


生成的查询如下所示:

UPDATE `stock` SET `signature_id`=0,`user_id`=0,`status_id`=1 WHERE `id` IN (1,3,5,6,10,11);INSERT INTO `returned` (`stock_id`,`signature_id`,`user_id`,`timestamp`) VALUES ('1','','',now()),('3','','',now()),('5','','',now()),('6','','',now()),('10','','',now()),('11','','',now());

10-06 04:59