MySQL - อัปเดตหลายแถวด้วยค่าที่แตกต่างกันในแบบสอบถามเดียว


151

ฉันพยายามทำความเข้าใจวิธีการอัปเดตหลายแถวด้วยค่าที่แตกต่างกัน แต่ฉันไม่เข้าใจ ทางออกมีอยู่ทุกที่ แต่สำหรับฉันแล้วมันดูยากที่จะเข้าใจ

ตัวอย่างเช่นการอัปเดตสามรายการใน 1 แบบสอบถาม:

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

คำตอบ:


207

คุณสามารถทำได้ด้วยวิธีนี้:

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. . . ฉันไม่เข้าใจความคิดเห็นของคุณ updates มีผลกับเรกคอร์ดที่มีอยู่แล้วเท่านั้น
Gordon Linoff

ขอโทษที่เป็นภาษาอังกฤษของฉันเมื่อฉันพยายามอัปเดต mysql ให้ข้อผิดพลาด: # 1062 - รายการซ้ำ 'XXX' สำหรับคีย์ 'PRIMARY' เมื่อฉันพยายามอัปเดตเรกคอร์ดที่มีค่าเดียวกับที่มีอยู่แล้วจะมีวิธีใดบ้างที่จะข้ามการอัปเดตหากค่าปัจจุบันเหมือนกับการอัปเดต
franvergara66

1
@ franvergara66. . . คุณอาจมีปัญหาอื่น หากcod_userเป็นคีย์หลักและกำลังสับค่าไปรอบ ๆ การอัปเดตหลายรายการน่าจะเป็นเส้นทางที่ดีที่สุด
Gordon Linoff

1
ใช่ฉันเห็นปัญหาที่แท้จริงคือมีผู้ช่วยหลายคนจากนั้นเมื่อพยายามทำการอัปเดตความสมบูรณ์ของคีย์หลักจะถูกละเมิด ขอบคุณมากสำหรับเวลาของคุณ.
franvergara66

120

MySQL ช่วยให้อ่านได้ง่ายขึ้นในการรวมการอัปเดตหลายรายการไว้ในแบบสอบถามเดียว สิ่งนี้ดูเหมือนจะเข้ากับสถานการณ์ที่คุณอธิบายได้ดีขึ้นอ่านง่ายกว่ามากและหลีกเลี่ยงเงื่อนไขหลายข้อที่ยากต่อการแก้ปัญหาเหล่านั้น

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รวมกันเป็นคีย์หลัก หากมีเพียงอันเดียวเท่านั้นที่เป็นคีย์หลักให้เพิ่มอีกช่องในรายการ UPDATE หากไม่มีทั้งสองเป็นคีย์หลัก (ซึ่งดูเหมือนไม่น่าจะเป็นไปได้) วิธีนี้จะสร้างระเบียนใหม่เสมอ - อาจไม่ใช่สิ่งที่ต้องการ

อย่างไรก็ตามวิธีนี้ทำให้งบที่เตรียมไว้สร้างง่ายขึ้นและรัดกุมมากขึ้น


4
ขอบคุณ! นี่คือสิ่งที่ฉันค้นหามาเป็นเวลานานวิธีที่ดูสะอาดตาที่สุดฉันไม่สามารถหาไวยากรณ์นี้ได้โดยเฉพาะcod_user=VALUES(cod_user), ...แม้แต่จากเอกสาร MySQL 5.6 อย่างเป็นทางการ
Yuriy Dyachkov

19
หมายเหตุ: สิ่งนี้จะเพิ่มแถวใหม่หากไม่มีคีย์ในตารางซึ่งส่งผลให้เกิดระเบียนที่ไม่ต้องการ
Faraz

1
ยุ่งยากในการใช้ IODKU ที่ไม่เคยใส่ แต่หรูหรามาก
Tom Desp

และโปรดทราบว่าแนวทางนี้ต้องมีการตั้งค่าคีย์หลักสำหรับตาราง
FlameStorm

5
สิ่งนี้จะไม่ได้ผลหากคุณละคอลัมน์ใด ๆ ที่ไม่สามารถเป็นค่าว่างได้เนื่องจาก sql ยังคงพยายามสร้างเรกคอร์ดใหม่ก่อนที่จะใช้การอัปเดตจริง
Arno van Oordt

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

9
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';

1

การขยายบน @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.