Drupal 7 |使用db_update更新多行

问题描述 投票:3回答:3

我有一个类似的数组

Array (
    [1] => 85590762,22412382,97998072
    [3] => 22412382 

)

其中key是item_id,value是我需要针对项更新的列的值。我可以在循环中使用db_update但我想避免这种策略由于性能。我想更新单个db调用中的所有行。同样使用db_query我认为不是一个好主意。那么有没有办法使用db_update来更新这些行?

根据以上数据,标准的mysql查询就像

update items set sold= 1, users = '85590762,22412382,97998072' Where item_id = 1; 
update items set sold = 1, users = '22412382' Where item_id = 3;
drupal drupal-7
3个回答
4
投票

不幸的是你做不到。目前和可能在该功能中,将不支持使用一个db_update更新具有不同值的不同行上的(多个)值。

如果您的数据是这样的:

$for_update = array(
  1 => "85590762,22412382,97998072",
  3 => "22412382",
);

你可以这样做:

情况1:每次更新功能时创建一个循环并调用:

foreach ($for_update as $key => $value) {
  $fields = array('sold' => 1, 'users' => $value);
  db_update('items')->fields($fields)->condition('item_id', $key, '=')->execute();
}

优点:其他模块可以挂钩查询,可以支持多个DB驱动程序 缺点:对象初始化很慢,很多数据库连接/流量

情况2:如果使用db_query(),速度会更快......

...因为在那种情况下没有对象实例化/操作,这有点昂贵和其他转换。 (即:https://drupal.stackexchange.com/questions/129669/whats-faster-db-query-db-select-or-entityfieldquery

foreach ($for_update as $key => $value) {
  db_query("UPDATE items SET sold = :sold, users = :users WHERE item_id = :item_id",
    array(':sold' => 1, ':users' => $value, ':item_id' => $key)
  );
}

优点:没有对象初始化和操作<所以它更快 缺点:其他模块无法挂钩查询,您的代码可能会破坏不同的数据库驱动程序,大量的数据库连接/流量

案例3:您也可以使用交易

在某些情况下,这可以提高您的性能。

$transaction = db_transaction();
try {
  foreach ($for_update as $key => $value) {
    $fields = array('sold' => 1, 'users' => $value);
    db_update('items')->fields($fields)->condition('item_id', $key, '=')->execute();
  }
}
catch (Exception $e) {
  $transaction->rollback();
  watchdog_exception('my_type', $e);
}

注意:交易主要用于,当你想要一切或什么也没有。但是对于某些DB驱动程序,您可以优化COMMIT命令。 在案例1中你会得到这样的东西:

UPDATE items SET sold = 1, users = '85590762,22412382,97998072' WHERE item_id = 1;
COMMIT;
UPDATE items SET sold = 1, users = '22412382' WHERE item_id = 3;
COMMIT;

通过事务,您可以执行以下操作:

UPDATE items SET sold = 1, users = '85590762,22412382,97998072' WHERE item_id = 1;
UPDATE items SET sold = 1, users = '22412382' WHERE item_id = 3;
COMMIT;

使用COMMIT,您可以将数据写入最终位置(进入长期存储,直到此,它只在内存中的某个位置或临时位置)。使用回滚时,将删除这些更改。至少这是我理解这一点的方式。 (当我使用sqlite时,我得到了性能提升。)

与案例1或2 +相同 优点:如果需要保持一致,可以回滚数据,只将数据写入驱动器一次<仅限sql“一次”执行IO,大量数据库连接/流量

情况4:或者您可以为此构建一个sql语句:

$ids = array();
$when_then = "";
foreach ($for_update as $key => $value) {
  $ids[] = $key;
  $when_then .= "WHEN $key THEN '$value' ";
}
db_query("UPDATE items
  SET sold = 1, users = CASE item_id 
                    $when_then
                    ELSE users
                    END
  WHERE item_id IN(:item_ids)", array(':item_ids' => $ids));

可能这是来自这里的最快的方式。 注意:$when_then变量不包含最佳解决方案,如果您可以使用参数或逃脱不安全数据,则更好。

优点:在你的服务器和sql之间只有一个请求和更少的冗余数据,一个更大的sql查询比很多小的查询更快 缺点:其他模块无法挂钩查询,您的代码可能会在不同的DB驱动程序下中断

另请注意,在(我认为)PHP 5.3之后,默认情况下你不能在db_query或PDO中运行多个语句,因为它可以是SQL注入,因此它会阻塞。但是你可以设置它,但不推荐。 (PDO support for multiple queries (PDO_MYSQL, PDO_MYSQLND)

13-05-2019编辑: 只是旁注,我几个月前在中等数据集上做了一些性能测量,通过db_selectdb_query查询一些数据。这些表现的大小是:在你运行一个db_select,你可以运行两个db_query。这也适用于db_updatedb_query。测试用一个简单的SELECT查询了一些列,没有JOINS,没有花哨的花花公子的东西,只有两个条件。当然,测量还包含/包括构建这些查询所需的时间(在两种情况下)。但是请注意,Drupal Coding Standard要求通常使用db_updatedb_deletedb_merge,只允许'允许'db_query而不是db_select操作。


0
投票

Using BULK UPDATE you can update multiple values on diferent rows or in the same row with the dinamic query db_update .

注意:通过批量更新,只能将一个查询发送到服务器,而不是每行要更新一个查询。

句法:

UPDATE yourTableName
SET yourUpdateColumnName = 
    (CASE yourConditionColumnName WHEN Value1 THEN 'UpdatedValue'
                                  WHEN Value2 THEN 'UpdatedValue'
     .
     .
     N
     END)
WHERE yourConditionColumnName IN(Value1,Value2,.....N);

有关UpdateQuery上的表达式的更多信息:https://api.drupal.org/api/drupal/includes%21database%21query.inc/function/UpdateQuery%3A%3Aexpression/7.x

您的数据将是:

//Create array
$for_update = [
    1 => "85590762,22412382,97998072",
    3 => "22412382",
];
$item_ids_to_filter = [];
//Setup when-then conditions
$when_then = "CASE item_id ";
foreach ($for_update as $item_id => $users_id) {
    $when_then .= "WHEN {$item_id} THEN '{$users_id}' ";
    $item_ids_to_filter[] = $item_id;
}
$when_then .= "END";
//Execute query and update the data with db_update
db_update('items')
->expression("users",$when_then)
->condition('item_id', $item_ids_to_filter)
->execute();

结果生成下一个查询:

UPDATE items
SET users =
       (CASE item_id =  WHEN 1 THEN '85590762,22412382,97998072'
                        WHEN 3 THEN '22412382'
        END)
WHERE (item_id IN  ('1', '3'))

-2
投票

我想你可以做点什么

$query = db_udpate('table')->fields(array('field_1','field_2','field_3'));
  foreach ($fields as $record) {
    $query->values($record);
  }
return $query->execute();

$ fields = array('field_1'=> VALUE,'field_2'=> VALUE)

© www.soinside.com 2019 - 2024. All rights reserved.