Bagaimana cara memperbarui dua tabel dalam satu pernyataan di SQL Server 2005?

193

Saya ingin memperbarui dua tabel sekaligus. Bagaimana saya melakukannya di SQL Server 2005?

UPDATE 
  Table1, 
  Table2
SET 
  Table1.LastName='DR. XXXXXX', 
  Table2.WAprrs='start,stop'
FROM 
  Table1 T1, 
  Table2 T2
WHERE 
  T1.id = T2.id
AND 
  T1.id = '010008'
Jango
sumber
4
Akan membantu jika Anda menjelaskan alasannya.
Eric Mickelsen
2
Saya khawatir, SQL server 2005 tidak mendukung pembaruan beberapa tabel dalam satu permintaan.
Pranav Singh

Jawaban:

194

Anda tidak dapat memperbarui beberapa tabel dalam satu pernyataan, namun, Anda dapat menggunakan transaksi untuk memastikan bahwa dua UPDATEpernyataan diperlakukan secara atomis. Anda juga dapat mengelompokkannya untuk menghindari perjalanan pulang pergi.

BEGIN TRANSACTION;

UPDATE Table1
  SET Table1.LastName = 'DR. XXXXXX' 
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

UPDATE Table2
SET Table2.WAprrs = 'start,stop'
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

COMMIT;
LBushkin
sumber
Sebenarnya, saya memperbarui catatan dua tabel ini dari temptable lain. temptable memiliki tautan ke table1 tetapi tidak table2. Bagaimana saya bisa memperbarui catatan Table2 yang sama? Bagaimana saya menautkannya?
Jango
@unknown: Berdasarkan komentar Anda, Anda harus bergabung di Table1 dan Table2 saat Anda memperbarui Table2 jika permintaan pembaruan Anda memerlukan kunci dari tabel ketiga. Terlepas dari itu, Anda masih perlu melakukan dua pembaruan terpisah.
LBushkin
3
mungkin tidak terkait: ini tidak akan berfungsi pada MYSQL karena sintaks pembaruan untuk mysql berbeda. Anda harus pergi UPDATE Table1, Table2 SET Table1.LastName = 'DR. XXXXXX 'WHERE T1.id = T2.id
Juan Vilar
apakah kita perlu mempertahankan kunci primer dan hubungan kunci asing di antara mereka
srinivas gowda
2
Anda juga harus meletakkan pernyataan pembaruan di dalam blok coba / tangkap untuk menghindari pembaruan sebagian jika terjadi kesalahan. lihat pertanyaan ini: stackoverflow.com/questions/1749719/…
mechatroner
84

Anda tidak bisa memperbarui dua tabel sekaligus, tetapi Anda bisa menautkan pembaruan ke dalam sisipan menggunakan OUTPUT INTO, dan Anda bisa menggunakan output ini sebagai gabungan untuk pembaruan kedua:

DECLARE @ids TABLE (id int);
BEGIN TRANSACTION

UPDATE Table1 
SET Table1.LastName = 'DR. XXXXXX'  
OUTPUT INSERTED.id INTO @ids
WHERE Table1.field = '010008';

UPDATE Table2 
SET Table2.WAprrs = 'start,stop' 
FROM Table2 
JOIN @ids i on i.id = Table2.id;

COMMIT;

Saya mengubah WHEREkondisi contoh Anda menjadi beberapa bidang selain id. Jika itu yang idAnda tidak perlu suka ini OUTPUT, Anda bisa hanya UPDATEmeja kedua untuk hal yang sama id='010008'.

Remus Rusanu
sumber
Ini adalah jawaban terbaik dan harus dipilih sebagai jawaban sebenarnya untuk pertanyaan awal. Terima kasih. Ini berhasil untuk saya.
Fandango68
1
Apakah itu T1.fieldseharusnya Table1.field?
WAF
22

Maaf, afaik, Anda tidak bisa melakukan itu. Untuk memperbarui atribut dalam dua tabel berbeda, Anda perlu menjalankan dua pernyataan terpisah. Tetapi mereka bisa dalam batch (satu set SQL dikirim ke server dalam satu perjalanan pulang pergi)

Charles Bretana
sumber
2
Astaga! Saya harus menggunakan kata Maaf lebih sering untuk pujian tambahan: P
Fandango68
14

Jawaban singkatnya adalah tidak. Meskipun Anda dapat memasukkan beberapa tabel dalam fromklausa pernyataan pembaruan, Anda hanya dapat menentukan satu tabel setelah updatekata kunci. Bahkan jika Anda menulis tampilan "yang dapat diupdate" (yang hanyalah tampilan yang mengikuti batasan tertentu), pembaruan seperti ini akan gagal. Berikut adalah klip yang relevan dari dokumentasi MSDN (penekanan ada pada saya).

UPDATE (Transact-SQL)

Tampilan yang dirujuk oleh table_or_view_name harus dapat diupdate dan merujuk tepat satu tabel dasar dalam klausa FROM dari view. Untuk informasi lebih lanjut tentang tampilan yang dapat diupdate, lihat CREATE VIEW (Transact-SQL).

BUAT LIHAT (Transact-SQL)

Anda bisa memodifikasi data tabel dasar yang mendasari melalui tampilan, selama kondisi berikut ini benar:

  • Setiap modifikasi, termasuk pernyataan UPDATE, INSERT, dan DELETE, harus merujuk kolom hanya dari satu tabel dasar .
  • Kolom yang sedang diubah dalam tampilan harus secara langsung merujuk data yang mendasarinya di kolom tabel. Kolom tidak dapat diturunkan dengan cara lain, seperti melalui yang berikut:
    • Fungsi agregat: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR, dan VARP.
    • Suatu perhitungan. Kolom tidak dapat dihitung dari ekspresi yang menggunakan kolom lain. Kolom yang dibentuk dengan menggunakan operator UNION, UNION ALL, CROSSJOIN, EXCEPT, dan INTERSECT berjumlah dalam perhitungan dan juga tidak dapat diperbarui.
  • Kolom yang sedang dimodifikasi tidak terpengaruh oleh klausa GROUP BY, HAVING, atau DISTINCT.
  • TOP tidak digunakan di mana pun dalam pernyataan select_statement bersama dengan klausa WITH CHECK OPTION.

Namun, dalam semua kejujuran, Anda harus mempertimbangkan untuk menggunakan dua pernyataan SQL yang berbeda dalam suatu transaksi sesuai dengan contoh LBushkin.

UPDATE: Pernyataan asli saya bahwa Anda dapat memperbarui beberapa tabel dalam tampilan yang dapat diupdate salah. Pada SQL Server 2005 & 2012, itu akan menghasilkan kesalahan berikut. Saya telah mengoreksi jawaban saya untuk mencerminkan hal ini.

Msg 4405, Level 16, State 1, Line 1

View or function 'updatable_view' is not updatable because the modification affects multiple base tables.

jveazey
sumber
1
Meskipun tidak mungkin untuk memperbarui objek tampilan yang akan memengaruhi banyak tabel, Anda bisa membuat BUKAN pemicu yang memecah dokumen asli menjadi pernyataan terpisah (masing-masing memengaruhi satu tabel):INSTEAD OF Specifies that the DML trigger is executed instead of the triggering SQL statement, therefore, overriding the actions of the triggering statements. INSTEAD OF cannot be specified for DDL or logon triggers.
4AM
9

Ini berfungsi untuk MySQL dan benar-benar hanya transaksi implisit tetapi harus seperti ini:

UPDATE Table1 t1, Table2 t2 SET 
t2.field = t2.field+2,
t1.field = t1.field+2

WHERE t1.id = t2.foreign_id and t2.id = '123414'

jika Anda melakukan pembaruan untuk multi tabel yang membutuhkan multi pernyataan ... yang mungkin terjadi jika Anda memperbarui satu, maka yang lain berdasarkan kondisi lain ... Anda harus menggunakan transaksi. 

pengguna3662407
sumber
1
Server ini masih relevan untuk pengguna lain.
Kyselejsyreček
1
@ Kyselejsyreček jawaban ini harus dihindari di semua biaya. MySQL memiliki cukup kebiasaan dan aroma, yang sebagian besar sebenarnya tidak didukung tetapi tetap dipertahankan untuk menghindari pemecahan kode yang tergantung pada kebiasaan tersebut. Memutakhirkan dapat dengan mudah memecahkannya atau menghasilkan masalah perilaku dan kinerja yang tidak terduga
Panagiotis Kanavos
7

Anda harus menempatkan dua laporan pembaruan dalam transaksi

Mick
sumber
2

Anda bisa menulis pernyataan pembaruan untuk satu tabel dan kemudian memicu pada pembaruan tabel pertama , yang memperbarui tabel kedua

Sandip - Pengembang Stack Lengkap
sumber
0

Dari sudut pandang saya, Anda dapat melakukan ini, pembaruan satu dari dua tabel di SQL SERVER:

 BEGIN TRANSACTION

      DECLARE @CNSREQ VARCHAR(30)
      DECLARE @ID INT
      DECLARE @CNSRQDT VARCHAR(30)
      DECLARE @ID2 INT

      DECLARE @IDCNSREQ INT
      DECLARE @FINALCNSREQ VARCHAR(30)
      DECLARE @FINALCNSRQDT VARCHAR(30)
      DECLARE @IDCNSRQDT INT


      SET @CNSREQ=(SELECT MIN(REQUISICIONESDT.CNSREQ) FROM REQUISICIONESDT
          INNER JOIN 
              REQUISICIONES
                ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
           AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID)

      SELECT REQUISICIONES.CNSREQ, REQUISICIONES.ID, REQUISICIONES.CNSRQDT FROM REQUISICIONES
       INNER JOIN 
          REQUISICIONESDT
              ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
               AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
    AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONESDT SET  REQUISICIONESDT.CNSREQ=NULL, REQUISICIONESDT.IDREQ=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
             ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
      AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT=NULL, REQUISICIONES.IDRQDT=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
          ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
     AND REQUISICIONES.CNSREQ = @CNSREQ

       SET @ID2=(SELECT MIN(REQUISICIONESDT.ID) FROM REQUISICIONESDT
        WHERE ISNULL(REQUISICIONESDT.IDREQ,0)<>0)
     DELETE FROM REQUISICIONESDT WHERE REQUISICIONESDT.ID=@ID2


      SET @IDCNSREQ=(SELECT MIN (REQUISICIONES.ID)FROM REQUISICIONES
          INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

        SET @FINALCNSREQ=(SELECT MIN (REQUISICIONES.CNSREQ)FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

         SET @FINALCNSRQDT=(SELECT MIN(REQUISICIONESDT.CNSRQDT) FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
          REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
           WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

          SET @IDCNSRQDT=(SELECT MIN (REQUISICIONESDT.ID)FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
         REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD  
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

           UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT = @FINALCNSRQDT, REQUISICIONES.IDRQDT=@IDCNSRQDT FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
             REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
            WHERE REQUISICIONESDT.CNSRQDT = @FINALCNSRQDT AND REQUISICIONESDT.ID = @IDCNSRQDT 


ROLLBACK TRANSACTION
Ricardo Roa
sumber
-2

Ini sesederhana permintaan yang ditunjukkan di bawah ini.

UPDATE 
  Table1 T1 join Table2 T2 on T1.id = T2.id
SET 
  T1.LastName='DR. XXXXXX', 
  T2.WAprrs='start,stop'
WHERE 
  T1.id = '010008'
Mohit Gupta
sumber