2012-04-01 20 views
6

bất cứ ai có thể cho tôi biết những gì kết quả như sau đây nên được theo tiêu chuẩn (một tham chiếu đến một phần đúng tiêu chuẩn sẽ được hoan nghênh)Tiêu chuẩn SQL nói gì về điều kiện "phụ thuộc" trong CẬP NHẬT?

> select * from t1; 
+------+ 
| col1 | 
+------+ 
| 9 | 
| 8 | 
| 10 | 
+------+ 
> update t1 
    set col1 = col1 * 2 
    where col1 <= (select avg(col1) from t1); 

Vấn đề là: Có hàng cuối cùng được cập nhật, vì nếu các hàng được cập nhật theo thứ tự và mức trung bình được tính toán lại cho mỗi hàng, nó sẽ đáp ứng điều kiện, hoặc nó không được cập nhật vì bất kỳ dữ liệu nào được thay đổi bởi câu lệnh này sẽ chỉ có thể đọc được sau khi toàn bộ câu lệnh được chạy?

EDIT Còn trường hợp này thì sao?

> select * from t1; 
+------+------+ 
| col1 | col2 | 
+------+------+ 
| 9 | 1 | 
| 8 | 2 | 
| 10 | 2 | 
+------+------+ 
> update t1 p1 
    set col1 = col1 * 2 
    where col1 <= (select avg(col1) 
        from t1 
        where col2=p1.col2); 
+0

Tại đây truy vấn con được thực hiện trước tiên. Vì vậy, trung bình không thay đổi. –

+0

@Shiplu Cảm ơn bạn. Và trường hợp thứ hai này, nơi truy vấn phụ không thể được thực hiện trước? – baruch

+1

@baruch - Nó có thể được thực hiện trước trong đó một hoạt động đọc riêng biệt xác định các hàng được cập nhật và lưu trữ các định danh hàng trong một ống hoặc tương tự, sau đó cập nhật được thực hiện đọc từ ống chỉ sau khi đọc xong. Đó là kế hoạch tôi mong đợi trong SQL Server. Bạn không chắc chắn tôi có thể bị bẻ khóa thông qua các tiêu chuẩn SQL để tìm các bit có liên quan mặc dù. Một vài khái niệm liên quan là "tất cả - tại - một lần hoạt động" và bảo vệ halloween. –

Trả lời

4

Theo như tôi có thể nói, tiêu chuẩn (chương 14.11, SQL 2003 - Foundation) là khá rõ ràng về vấn đề này:

được đánh giá có hiệu quả cho mỗi hàng của T trước bất kỳ hàng của T được cập nhật

(tôi nhấn mạnh)

sự hiểu biết của tôi về câu nói đó là bất kỳ điều kiện (cho dù đồng có liên quan hoặc không) được đánh giá trước khi bất kỳ hàng được cập nhật.

+0

... và một phổ biến (nếu không phải là DBMS duy nhất) không phù hợp với tiêu chuẩn - và tương tự như các truy vấn ví dụ có thể dẫn đến kết quả không chuẩn - là MySQL. –

+0

@ypercube: tại sao tôi không ngạc nhiên? –

+1

Thành thật mà nói, đây là một trong những nghiêm trọng nhất, nếu không phải là nghiêm trọng nhất, sai lệch so với các tiêu chuẩn. Thậm chí đơn giản 'UPDATE t SET id = id + 1' được thực hiện theo cách nối tiếp và không phải là một thao tác được đặt, và sẽ dẫn đến vi phạm PK. –

2

Hàng cuối cùng sẽ không được cập nhật. vì "chọn avg (col1) từ t1" là một truy vấn phụ, và nó sẽ chạy trước tiên, và lưu trữ kết quả trong bảng tạm thời, sau đó câu lệnh cập nhật sẽ thực thi.

+0

Cảm ơn bạn. Bạn có thể xem bản chỉnh sửa của tôi không? – baruch

4

Về truy vấn đầu tiên, các subquery tiên thực hiện trước như vậy, không có thay đổi trong mức trung bình ...

Về truy vấn thứ hai, bạn đang sử dụng bí danh trong UPDATE tuyên bố nhưng bạn đang sử dụng bí danh trong cách tiếp cận sai.

cách chính xác và tiêu chuẩn để sử dụng bí danh trong UPDATE tuyên bố là:

UPDATE p1 
    set col1 = col1 * 2 
from t1 p1 
    where col1 <= (select avg(col1) 
        from t1 
        where col2=p1.col2); 
+2

Chuẩn SQL không cho phép mệnh đề 'FROM' cho câu lệnh' UPDATE'. Vì vậy, ví dụ của bạn không phải là "cách tiêu chuẩn". Ngoài ra trong tiêu chuẩn SQL, bí danh bảng được định nghĩa trong phần 'UPDATE':' UPDATE [[AS] ] '. Cú pháp trên chỉ hợp lệ cho MySQL nếu tôi không nhầm –

+0

@ a_horse_with_no_name: Cảm ơn bạn .... Nó hoạt động trên MS-SQL Server .. Tôi đã thử nghiệm trên truy vấn trong MSSQL Nhưng khi tôi thực hiện truy vấn thứ hai của OP, nó ném lỗi ... –

+0

cảm ơn bạn đã cập nhật. –

Các vấn đề liên quan