Làm cách nào để cập nhật hai bảng trong một câu lệnh trong SQL Server 2005?


193

Tôi muốn cập nhật hai bảng trong một lần. Làm cách nào để làm điều đó trong 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'

4
Nó sẽ giúp nếu bạn giải thích lý do tại sao.
Eric Mickelsen

2
Tôi e rằng, máy chủ SQL 2005 không hỗ trợ cập nhật nhiều bảng trong một truy vấn.
Pranav Singh

Câu trả lời:


194

Bạn không thể cập nhật nhiều bảng trong một câu lệnh, tuy nhiên, bạn có thể sử dụng một giao dịch để đảm bảo rằng hai UPDATEcâu lệnh được xử lý nguyên tử. Bạn cũng có thể bó chúng để tránh một chuyến đi khứ hồi.

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;

Trên thực tế, tôi đang cập nhật hồ sơ của hai bảng này từ một cám dỗ khác. cám dỗ có liên kết đến bảng1 nhưng không liên kết với bảng2. Làm thế nào tôi có thể cập nhật cùng một bản ghi của Bảng2? Làm thế nào tôi sẽ liên kết nó?
Jango

@unknown: Dựa trên nhận xét của bạn, bạn sẽ cần tham gia trên cả Bảng1 và Bảng2 khi bạn cập nhật Bảng2 nếu truy vấn cập nhật của bạn cần các khóa từ bảng thứ ba. Bất kể điều đó, bạn vẫn cần phải thực hiện hai bản cập nhật riêng biệt.
LBushkin

3
có lẽ không liên quan: điều này sẽ không hoạt động trên MYSQL vì cú pháp cập nhật cho mysql là khác nhau. bạn phải truy cập CẬP NHẬT Bảng1, Bảng2 BỘ Bảng1.LastName = 'DR. XXXXXX 'WHERE T1.id = T2.id
Juan Vilar

chúng ta có cần duy trì quan hệ khóa chính và khóa ngoại giữa chúng không
srinivas gowda

2
Bạn cũng nên đặt các câu lệnh cập nhật của mình bên trong khối try / Catch để tránh cập nhật một phần trong trường hợp có lỗi. xem câu hỏi này: stackoverflow.com/questions/1749719/ Cách
mechatroner

84

Bạn không thể cập nhật hai bảng cùng một lúc, nhưng bạn có thể liên kết một bản cập nhật thành một phần chèn bằng cách sử dụng OUTPUT INTOvà bạn có thể sử dụng kết quả đầu ra này như một phép nối cho bản cập nhật thứ hai:

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;

Tôi đã thay đổi WHEREđiều kiện ví dụ của bạn thành một số lĩnh vực khác id. Nếu đó là idbạn không cần sự ưa thích này OUTPUT, bạn có thể chỉ cần UPDATEbàn thứ hai cho cùng id='010008'.


Đây là câu trả lời tốt nhất và nên được bình chọn là câu trả lời thực sự cho câu hỏi ban đầu. Cảm ơn bạn. Nó làm việc cho tôi.
Fandango68

1
Đó có T1.fieldphải là Table1.field?
WAF

22

Xin lỗi, afaik, bạn không thể làm điều đó. Để cập nhật các thuộc tính trong hai bảng khác nhau, bạn sẽ cần thực hiện hai câu lệnh riêng biệt. Nhưng chúng có thể theo một đợt (một bộ SQL được gửi đến máy chủ trong một chuyến đi khứ hồi)


2
Trời ạ! Tôi nên sử dụng từ Xin lỗi thường xuyên hơn để có thêm danh tiếng: P
Fandango68

14

Câu trả lời ngắn gọn là không. Mặc dù bạn có thể nhập nhiều bảng trong frommệnh đề của câu lệnh cập nhật, bạn chỉ có thể chỉ định một bảng sau updatetừ khóa. Ngay cả khi bạn viết chế độ xem "có thể cập nhật" (đơn giản là chế độ xem tuân theo các hạn chế nhất định), các cập nhật như thế này sẽ thất bại. Dưới đây là các clip có liên quan từ tài liệu MSDN (nhấn mạnh là của tôi).

CẬP NHẬT (Giao dịch-SQL)

Chế độ xem được tham chiếu bởi table_or_view_name phải được cập nhật và tham chiếu chính xác một bảng cơ sở trong mệnh đề TỪ của chế độ xem. Để biết thêm thông tin về các chế độ xem có thể cập nhật, hãy xem CREATE VIEW (Transact-SQL).

TẠO XEM (Giao dịch-SQL)

Bạn có thể sửa đổi dữ liệu của bảng cơ sở bên dưới thông qua chế độ xem, miễn là các điều kiện sau là đúng:

  • Bất kỳ sửa đổi nào, bao gồm các câu lệnh CẬP NHẬT, CHERTN và XÓA, phải tham chiếu các cột từ chỉ một bảng cơ sở .
  • Các cột được sửa đổi trong dạng xem phải tham chiếu trực tiếp dữ liệu cơ bản trong các cột của bảng. Các cột không thể được dẫn xuất theo bất kỳ cách nào khác, chẳng hạn như thông qua các điều sau đây:
    • Một hàm tổng hợp: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR và VARP.
    • Một tính toán. Cột không thể được tính từ một biểu thức sử dụng các cột khác. Các cột được hình thành bằng cách sử dụng các toán tử tập hợp UNION, UNION ALL, CROSSJOIN, EXCEPT và INTERSECT cho một tính toán và cũng không thể cập nhật.
  • Các cột được sửa đổi không bị ảnh hưởng bởi các mệnh đề GROUP BY, HAVING hoặc DISTINCT.
  • TOP không được sử dụng ở bất cứ đâu trong select_statement của chế độ xem cùng với mệnh đề VỚI KIỂM TRA TÙY CHỌN.

Tuy nhiên, trong tất cả sự trung thực, bạn nên xem xét sử dụng hai câu lệnh SQL khác nhau trong một giao dịch theo ví dụ của LBushkin.

CẬP NHẬT: Khẳng định ban đầu của tôi rằng bạn có thể cập nhật nhiều bảng trong chế độ xem cập nhật là sai. Trên SQL Server 2005 & 2012, nó sẽ tạo ra lỗi sau. Tôi đã sửa câu trả lời của mình để phản ánh điều này.

Msg 4405, Level 16, State 1, Line 1

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


1
Mặc dù không thể cập nhật một đối tượng View sẽ ảnh hưởng đến nhiều bảng, nhưng bạn có thể tạo các trình kích hoạt INSTEAD OF phá vỡ bản gốc thành các câu lệnh riêng biệt (ảnh hưởng đến một bảng mỗi bảng):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

Điều này hoạt động với MySQL và thực sự chỉ là một giao dịch ngầm nhưng nó sẽ diễn ra như thế này:

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'

nếu bạn đang thực hiện cập nhật lên nhiều bảng yêu cầu nhiều câu lệnh có thể có khả năng nếu bạn cập nhật một bảng, thì một bảng khác dựa trên các điều kiện khác, bạn nên sử dụng một giao dịch. 


1
Anser này vẫn có liên quan cho người dùng khác.
Kyselejsyreček

1
@ Kyselejsyreček câu trả lời này nên tránh bằng mọi giá. MySQL có đủ quirks và mùi, hầu hết trong số đó thực sự không được hỗ trợ nhưng được giữ lại để tránh phá mã phụ thuộc vào các quirks đó. Nâng cấp có thể dễ dàng phá vỡ chúng hoặc dẫn đến các vấn đề về hành vi và hiệu suất không mong muốn
Panagiotis Kanavos

7

Bạn nên đặt hai báo cáo cập nhật bên trong một giao dịch



0

Từ quan điểm của tôi, bạn có thể làm điều này, cập nhật một đến hai bảng trong 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

-2

Nó đơn giản như truy vấn này được hiển thị dưới đây.

UPDATE 
  Table1 T1 join Table2 T2 on T1.id = T2.id
SET 
  T1.LastName='DR. XXXXXX', 
  T2.WAprrs='start,stop'
WHERE 
  T1.id = '010008'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.