Drupal 7 / actualizar várias linhas com a actualização do db

tenho uma matriz como

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

)

onde a chave é o item_id e o valor é o valor de uma coluna que preciso actualizar em relação a um item. Eu posso usar DB_ Update em um loop mas eu quero evitar esta estratégia devido ao desempenho. Eu quero atualizar todas as linhas em uma única chamada db. Também usando db_query eu acho que não será uma boa idéia. Existe alguma forma de usar o DB_ Update para actualizar estas linhas?

de acordo com os dados acima, as consultas padrão do mysql serão como

update items set sold= 1, users = '85590762,22412382,97998072' Where item_id = 1; 
update items set sold = 1, users = '22412382' Where item_id = 3;
Author: Tausif Khan, 2014-09-03

2 answers

Infelizmente não podes fazer isso. De momento e provavelmente na funcionalidade, não haverá suporte para atualização (múltiplos) valores em diferentes linhas com valores diferentes com um DB_ update.

Se os seus dados são estes:

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

Podes fazer isto:

Caso 1: Criar um ciclo e ligar sempre que a função de actualização:

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

Prós: outros módulos podem encaixar-se dentro da sua pesquisa, podem suportar múltiplos drivers de DB
Cons: a inicialização do objecto é lenta, muito DB ligação / tráfego

Caso 2: é mais rápido se você usar db_query()...

... porque nesse caso não há instanciação/Operação de objeto, o que é um pouco caro e outra conversão. (isto é: 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)
  );
}
Prós: sem inicialização de objetos e operação por isso é mais rápido
Cons: outros módulos não podem se conectar dentro de sua consulta, seu código pode quebrar sob DB diferente condutores, muita ligação DB/tráfego

Caso 3: também pode usar a transacção

Isto pode aumentar um pouco o teu desempenho em algum caso.
$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);
}

Nota: transacção utilizada principalmente, quando se quer tudo ou nada. Mas com alguns drivers DB, você pode otimizar os comandos COMMIT.
No caso de se ter algo assim:

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;

Com a transacção fazes algo assim:

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;

Com o COMMIT você escreve os dados para o local final (em armazenamento de longo prazo, até isso, é apenas em algum lugar na memória ou um lugar temporário). Quando você usa rollback, você deixa cair essas alterações. Pelo menos é assim que eu entendo isto. (ou seja, eu recebo melhoria de desempenho com isso quando eu usei sqlite.)

O mesmo que o caso 1 ou 2 +
Prós: você pode rever os seus dados se você precisa ser consistente, você escreve os dados apenas uma vez para a unidade Caso 4: ou pode construir um sql declaração para isto:

$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));
Provavelmente este é o caminho mais rápido a partir daqui.
Nota: $when_then a variável não contém a melhor solução, é melhor se puder usar os parâmetros ou escapar a dados inseguros.

Prós: entre o seu servidor e o sql haverá apenas um pedido e dados menos redundantes, uma maior pesquisa de sql mais rápido do que muitos pequenos
Cons: outros módulos não podem entrar na sua consulta, o seu código pode quebrar sob diferentes drivers de DB

Também por favor, note, após (eu acho) PHP 5.3 você não pode executar mais de uma declaração em db_query ou na DOP por padrão, por causa de que pode ser uma injeção SQL, por isso bloqueia. No entanto, você pode definir isso, mas não recomendado. ( suporte DOP para múltiplas consultas (PDO_MYSQL, PDO_MYSQLND))

 2
Author: golddragon007, 2017-08-31 17:02:20
Acho que podias fazer algo como ...
$query = db_udpate('table')->fields(array('field_1','field_2','field_3'));
  foreach ($fields as $record) {
    $query->values($record);
  }
return $query->execute();

Em que $fields = array ('field_1' = > valor,' field_2 ' = > valor)

 -2
Author: Lokisho, 2014-09-05 04:02:38