MySQL-1つのクエリで異なる値を持つ複数の行を更新する


139

異なる値を持つ複数の行を更新する方法を理解しようとしていますが、取得できません。解決策はどこにでもありますが、私には理解するのが難しいようです。

たとえば、1つのクエリへの3つの更新:

UPDATE table_users
SET cod_user = '622057'
    , date = '12082014'
WHERE user_rol = 'student'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '2913659'
    , date = '12082014'
WHERE user_rol = 'assistant'
    AND cod_office = '17389551'; 

UPDATE table_users
SET cod_user = '6160230'
    , date = '12082014'
WHERE user_rol = 'admin'
    AND cod_office = '17389551'; 

例を読みましたが、クエリの作成方法がよくわかりません。つまり:

UPDATE table_to_update
SET cod_user= IF(cod_office = '17389551','622057','2913659','6160230')
    ,date = IF(cod_office = '17389551','12082014')
WHERE ?? IN (??) ;

WHERE条件とIF条件に複数の条件がある場合、クエリの実行方法が完全にわかりません。


これはあなたの質問に答えますか?MySQLの複数の更新
PeterPan666

回答:


186

あなたはこの方法でそれを行うことができます:

UPDATE table_users
    SET cod_user = (case when user_role = 'student' then '622057'
                         when user_role = 'assistant' then '2913659'
                         when user_role = 'admin' then '6160230'
                    end),
        date = '12082014'
    WHERE user_role in ('student', 'assistant', 'admin') AND
          cod_office = '17389551';

日付の形式がわかりません。日付は、ネイティブの日付と時刻タイプを使用してデータベースに格納する必要があります。


レコードがすでに存在する場合、更新が実行されるようにするにはどうすればよいですか
franvergara66

1
@ franvergara66。。。コメントが理解できません。 update■すでに存在するレコードにのみ影響します。
ゴードンリノフ2014

失礼します。更新を作成しようとすると、mysqlでエラーが発生します。#1062-キー「PRIMARY」のエントリ「XXX」が重複しています。それは私がすでに持っていた同じ値でレコードを更新しようとすると、現在の値が更新されているものと同じである場合、更新をスキップする方法はありますか?
franvergara66 2014

1
@ franvergara66。。。別の問題がある可能性があります。場合はcod_user、主キーで、値が周りシャッフルされ、その後、複数の更新は、おそらく最良のルートです。
ゴードンリノフ2014

1
うん、本当の問題は、アシスタントがいくつかいるということです。更新を行おうとすると、主キーの整合性が損なわれます。お時間をいただき、誠にありがとうございます。
franvergara66 2014

108

MySQLでは、複数の更新を1つのクエリに組み合わせる、より読みやすい方法を使用できます。これは、あなたが説明するシナリオによりよく適合しているようで、読みやすく、複数の条件を解くことが困難な状況を回避できます。

INSERT INTO table_users (cod_user, date, user_rol, cod_office)
VALUES
('622057', '12082014', 'student', '17389551'),
('2913659', '12082014', 'assistant','17389551'),
('6160230', '12082014', 'admin', '17389551')
ON DUPLICATE KEY UPDATE
 cod_user=VALUES(cod_user), date=VALUES(date)

これは、user_rol, cod_office組み合わせが主キーであることを前提としています。これらの1つだけが主キーである場合は、他のフィールドをUPDATEリストに追加します。どちらも主キーでない場合(それはありそうもないようです)、このアプローチでは常に新しいレコードが作成されます。

ただし、このアプローチにより、準備済みステートメントの作成がより簡単になり、簡潔になります。


4
ありがとうございました!これは私が長い間探していたものであり、最もきれいに見える方法です。特にcod_user=VALUES(cod_user), ...、公式のMySQL 5.6ドキュメント
Yuriy Dyachkov

18
注:これにより、テーブルにキーが存在しない場合に新しい行が追加され、不要なレコードが生成されます。
ファラス

1
決して挿入しないIODKUを使用するのはトリッキーですが、非常にエレガントです。
Tom Desp

また、この方法ではテーブルに主キーが設定されている必要があることに注意してください。
FlameStorm 2017

5
SQLは実際に更新を行う前に新しいレコードを作成しようとするため、nullにできない列を省略した場合、これは機能しません。
Arno van Oordt 2017年

15

CASEステートメントを使用して、複数のif / thenシナリオを処理できます。

UPDATE table_to_update 
SET  cod_user= CASE WHEN user_rol = 'student' THEN '622057'
                   WHEN user_rol = 'assistant' THEN '2913659'
                   WHEN user_rol = 'admin' THEN '6160230'
               END
    ,date = '12082014'
WHERE user_rol IN ('student','assistant','admin')
  AND cod_office = '17389551';

1
CASEステートメントの最後にタイプミスをしました。隣り合わせに2つのコンマがあります。
pmrotule 2015

8
update table_name
set cod_user = 
    CASE 
    WHEN user_rol = 'student' THEN '622057'
    WHEN user_rol = 'assistant' THEN '2913659'
    WHEN user_rol = 'admin' THEN '6160230'?
    END,date = '12082014'

WHERE user_rol IN ('student','assistant','admin')
AND cod_office = '17389551';

0

@Trevedhekの回答を拡張するには

一意でないキーで更新を行う必要がある場合は、4つのクエリが必要になります

注:これはトランザクションセーフではありません

これは、一時テーブルを使用して行うことができます。

手順1:更新する一時テーブルのキーと列を作成する

CREATE TEMPORARY TABLE  temp_table_users
(
    cod_user varchar(50)
    , date varchar(50)
    , user_rol varchar(50)
    ,  cod_office varchar(50)
) ENGINE=MEMORY

手順2:一時テーブルに値を挿入する

ステップ3:元のテーブルを更新する

UPDATE table_users t1
JOIN temp_table_users tt1 using(user_rol,cod_office)
SET 
t1.cod_office = tt1.cod_office
t1.date = tt1.date

手順4:一時テーブルを削除する


0
UPDATE Table1 SET col1= col2 FROM (SELECT col2, col3 FROM Table2) as newTbl WHERE col4= col3

ここで、col4とcol1はTable1にあります。col2とcol3はTable2
にあります各col1を更新しようとしています。ここで、col4 = col3は各行に異なる値です。


-1

私はこのようにしました:

<update id="updateSettings" parameterType="PushSettings">
    <foreach collection="settings" item="setting">
        UPDATE push_setting SET status = #{setting.status}
        WHERE type = #{setting.type} AND user_id = #{userId};
    </foreach>
</update>

ここで、PushSettingsは

public class PushSettings {

    private List<PushSetting> settings;
    private String userId;
}

それはうまくいきます


著者は1つのクエリを望んでいますが、foreachを使用してそれを実行できることは明らかです。これにより、いくつかのクエリが作成されます
Hristo93
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.