単一の SQL クエリで複数の更新を行うにはどうすればよいですか?
質問
次の形式の SQL クエリがあります。
UPDATE foo
SET flag=true
WHERE id=?
ID のリストを含む PHP 配列もあります。次のように、解析以外にこれを達成する最良の方法は何ですか...
foreach($list as $item){
$querycondition = $querycondition . " OR " . $item;
}
...そしてその出力を使用して、 WHERE
句?
解決
これは同じことを達成しますが、おそらく速度はあまり向上しませんが、見た目は良くなります。
mysql_query("UPDATE foo SET flag=true WHERE id IN (".implode(', ',$list).")");
他のヒント
IN 句を使用できるはずです (データベースが IN 句をサポートしていると仮定します)。
UPDATE foo
SET flag=true
WHERE id in (1, 2, 3, 5, 6)
IN ステートメントを使用します。キー値のカンマ区切りのリストを指定します。を使用すると簡単にそれを行うことができます implode
関数。
UPDATE foo SET flag = true WHERE id IN (1, 2, 3, 4, 5, ...)
あるいは、条件を使用することもできます。
UPDATE foo SET flag = true WHERE flag = false
またはサブクエリ:
UPDATE foo SET flag = true WHERE id IN (SELECT id FROM foo WHERE .....)
join/implode を使用して、最終的に次のようになるカンマ区切りのリストを作成します。
UPDATE foo SET flag=true WHERE id IN (1,2,3,4)
foreach ループ以外にそれを行う方法を見たことがありません。
ただし、何らかの方法で $list をユーザーから取得した場合は、プリペアド ステートメントを使用し、一度に 1 行ずつ更新することに固執する必要があります (プリペアド ステートメントで複数の行を更新する方法がないと仮定して)。それ以外の場合は、SQL インジェクションの可能性が広がります。
case ステートメントを使用して更新することもできますが、クエリを自分で作成する必要があります。
UPDATE foo
SET flag=CASE ID WHEN 5 THEN true ELSE flag END
,flag=CASE ID WHEN 6 THEN false ELSE flag END
WHERE id in (5,6)
where は省略できますが、テーブル全体を更新する手間が省けます。
VB.NET コード:dim delimitedIdList as string = arrayToString(listOfIds)
dim SQL as string = " UPDATE foo SET flag=true WHERE id in (" + delimitedIdList + ")"
runSql(SQL)
項目数の上限がわかっている場合は、他の人が提案しているように、「IN」句を使用します。
UPDATE foo SET flag=true WHERE id in (1, 2, 3, 5, 6)
ただし、データベースによっては、句内の要素の数に制限がある場合があるという警告が 1 つあります。たとえば、oracle 7 または 8 (?) では、以前は 256 項目の制限がありました (これは、後のバージョンでは大幅に増加しました)
リストを反復処理する場合は、更新の 1 つが失敗した場合にロールバックできるようにトランザクションを使用します。