2013-01-24 38 views
9

Tôi mới trong PostgreSQL và đang cố chuyển đổi truy vấn từ SQL Server.Cập nhật Postgres từ bên trái tham gia

Tôi có một bảng Người dùng với, trong số những người khác, các cột bUsrActive, bUsrAdmin và sUsrClientCode. Tôi muốn cập nhật người dùng và đặt bUsrActive = false nếu không tồn tại một người dùng khác có cùng sUsrClientCode trong đó bUsrAdmin = true và bUsrActive = true.

Trong SQL Server Tôi có truy vấn này

UPDATE u SET u.bUsrActive = 0 
FROM Users u 
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 

Tôi đang cố gắng để chuyển đổi này để postgres. Tôi đã viết 3 cách tiếp cận.

1) Lần thử đầu tiên của tôi. Rõ ràng là không hoạt động.

UPDATE Users u 
    SET bUsrActive = false 
FROM Users u2 
WHERE u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true 
AND u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL; 

2) Tôi hiểu tại sao nó không hoạt động (cập nhật tất cả người dùng). Tôi chỉ không thể tìm ra làm thế nào tôi có thể tham khảo người dùng bảng u trong phần UPDATE ... SET.

UPDATE Users 
    SET bUsrActive = false 
FROM Users u 
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true 
WHERE u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL; 

3) Phần sau đây hoạt động nhưng không sử dụng kết nối.

UPDATE Users 
    SET bUsrActive = false 
WHERE NOT EXISTS (
    SELECT 1 
    FROM Users u 
    WHERE u.sUsrClientCode = Users.sUsrClientCode AND u.bUsrAdmin = true AND u.bUsrActive = true 
) AND Users.bUsrAdmin = false AND Users.bUsrActive = true; 

Tôi có thể sẽ đi với giải pháp cuối cùng. Tôi chỉ muốn biết nếu nó có thể làm những gì tôi muốn bằng cách sử dụng một tham gia trái.

+1

Điều gì xảy ra với phiên bản thứ ba? –

+1

Không có gì, nó hoạt động. Chỉ cần tự hỏi nếu tôi có thể làm điều đó theo cách khác bằng cách sử dụng tham gia. Có vẻ đẹp hơn cho mắt! Tôi đoán hiệu suất sẽ giống nhau. – alfoks

+0

Cách thứ hai sẽ hoạt động (ngay từ cái nhìn đầu tiên) lỗi bạn nhận được là gì ?. Bạn có biết rằng ngữ nghĩa của mệnh đề 'FROM' khác trong PostgreSQL so với SQL Server không? –

Trả lời

12

Đây là một cách tổng quát để chuyển đổi này truy vấn cập nhật từ hình thức SQL-server để PostgreSQL:

UPDATE Users 
SET bUsrActive = false 
WHERE 
ctid IN (
    SELECT u.ctid FROM Users u 
     LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
    WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 
) 

ctid là một pseudo-cột trỏ đến vị trí độc đáo của một hàng. Bạn có thể sử dụng thay vì khóa chính của bảng nếu nó có một.

Truy vấn # 2 từ câu hỏi không làm những gì bạn mong đợi vì bảng được cập nhật Users không bao giờ được nối với cùng một bảng Users u trong mệnh đề FROM. Cũng giống như khi bạn đặt tên bảng hai lần trong mệnh đề FROM, chúng không được tham gia hoặc ràng buộc hoàn toàn với nhau, chúng được coi là hai tập hợp các hàng độc lập.

+0

Cảm ơn bạn đã trả lời. Có vẻ như những gì tôi yêu cầu không thể làm được. Tôi có nghĩa là trong trường hợp truy vấn # 2 không có một cách để tham khảo bảng u bằng cách nào đó. Dù sao tôi sẽ có trong tâm trí của bạn giải pháp để tham khảo trong tương lai và có thể truy vấn phức tạp hơn. Bây giờ tôi sẽ đi với truy vấn thứ 3. – alfoks

1

Tôi nghĩ đây là cách thực hiện đúng 2) Tôi tin rằng nó tối ưu/hiệu quả hơn so với thực hiện lựa chọn phụ.

UPDATE Users uOrig 
    SET bUsrActive = false 
FROM Users u 
     LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 
    and uOrig.sUsrClientCode = u.sUsrClientCode; 
+0

Tôi không cài đặt Postgres nữa và đã 2 năm kể từ khi tôi sử dụng lần cuối, nhưng tôi tin rằng truy vấn của bạn không đúng về cú pháp. Nếu không truy vấn đầu tiên của tôi cũng sẽ hoạt động. Nếu tôi nhớ chính xác, trong Postgres bạn không thể bí danh bảng bạn đang cập nhật. – alfoks

+2

bạn có thể đặt tên cho bảng mà bạn đang cập nhật. Bạn không thể sử dụng bí danh đó trong mệnh đề SET. –

+0

Đây không phải là cú pháp chính xác. –

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