2011-04-05 25 views
9

Tuyên bố CẬP NHẬT của tôi đi theo các dòng:SQL - Cập nhật với câu lệnh CASE, tôi có cần phải lặp lại cùng một CASE nhiều lần không?

UPDATE customer 
SET forenames=ot.forenames, 
    surname = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test SAFEPLACE IS NULL' 
ELSE 'test Safeplace IS NOT NULL' 
END, 

    middlename = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test2 SAFEPLACE IS NULL' 
ELSE 'test2 Safeplace IS NOT NULL' 
END, 

FROM order_transaction ot 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 

Các công trình trên. Về cơ bản nó kiểm tra nếu một trường trong bảng khác là NULL hay không, và sau đó cập nhật "họ của họ" và "middlename" cho phù hợp. Như bạn có thể thấy ở trên, tôi đã lặp lại cùng một câu lệnh CASE hai lần. Câu hỏi của tôi là - có cách nào tôi có thể chỉ định tuyên bố CASE chỉ một lần?

Vấn đề là, nếu tôi muốn cập nhật 10 trường dựa trên một điều kiện nhất định, tôi có cần bao gồm 10 điều kiện CASE tương tự không? Hoặc SQL có thể được cải thiện để chỉ có một CASE và 10 cập nhật trường trong mệnh đề WHEN/ELSE không?

(Tôi đang sử dụng cơ sở dữ liệu Postgresql 8.2 nhưng tôi tin rằng ở trên là SQL chuẩn).

Rất cám ơn, Rishi

Trả lời

3

Nếu bạn muốn thực hiện điển hình về mức độ truy vấn tương tự, bạn sẽ cần phải lặp lại CASE, cũng giống như bạn sẽ lặp lại một cột tính trong một nhóm bởi khoản.

truy vấn mẫu của bạn không tiết lộ tất cả những gì bạn muốn làm, bạn có thực sự cập nhật tất cả hồ sơ để các giá trị như nhau (văn bản cố định), cũng như tất cả cột cho mỗi bản ghi. Nếu bạn cập nhật để làm cho câu hỏi phù hợp hơn, có lẽ có một câu trả lời tốt hơn.


Nhưng bây giờ, đối với truy vấn cụ thể, bạn có thể sử dụng một cái gì đó như thế này

UPDATE customer 
SET forenames=ot.forenames, 
    surname = fixedText, 
    middlename = fixedText  
FROM (select o.*, CASE 
     WHEN safeplace IS NULL 
     THEN 'test2 SAFEPLACE IS NULL' 
     ELSE 'test2 Safeplace IS NOT NULL' 
     END fixedText 
     from order_transaction o) ot 
WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
+0

Không thực sự là giải pháp tốt nhất Richard.Khi lựa chọn đầu tiên của bạn quét bảng và thêm kết quả và sau đó chọn lọc nó. –

+1

@Dumitrescu Bogdan/Tôi không nghĩ rằng nó làm điều đó. Bởi vì PostgreSQL sẽ hủy truy vấn để áp dụng các bộ lọc vào truy vấn phụ, nhưng vẫn giữ khả năng sử dụng cột được xác định (được tính toán) – RichardTheKiwi

+0

Cú pháp của OP không phải là tiêu chuẩn SQL (cũng lưu ý rằng tiêu chuẩn SQL là quốc tế và 'A' trong 'ANSI' là viết tắt của 'American' nên "SQL tuân thủ ISO" sẽ phù hợp hơn ở đây :) – onedaywhen

0

Nếu bạn cần phải sao chép các trường hợp chính xác nhiều lần (rất nhiều hơn sau đó 2), bạn có thể sử dụng các truy vấn tiếp theo. Nhưng bạn phải thực sự cần phải sao chép các trường hợp, không phải với thử nghiệm và test2 (đó không phải là chính xác cùng một trường hợp). Rõ ràng nếu bạn cần ghép nối văn bản như kiểm tra/thử nghiệm 2 hoặc bất kỳ kết quả nào thì bạn có thể làm điều đó trong câu lệnh chọn. ví dụ: họ = 'test' + st.result nên có một số khả năng để thực hiện một số 'hack'.

UPDATE customer 
SET forenames=ot.forenames, 
    surname = st.result, 
    middlename = st.result 

FROM order_transaction ot 
JOIN (select 1 as ID,'test SAFEPLACE IS NULL' as result 
     union 
     select 2,'test SAFEPLACE IS NULL') st on case when ot.safeplace is null then 1 else 2 end = st.id 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
7

Tôi tin rằng ở trên là tiêu chuẩn SQL

Trên thực tế, nó không phải là. SQL chuẩn không có cú pháp UPDATE..FROM. Thay vào đó, bạn cần phải sử dụng truy vấn con vô hướng cho mỗi mệnh đề SET cộng với một mệnh đề khác cho EXISTS, do đó cú pháp chuẩn thậm chí lặp lại nhiều hơn, ví dụ:

UPDATE customer 
    SET forenames = (
        SELECT ot.forenames 
         FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ), 
     surname = (
        SELECT CASE 
          WHEN ot.safeplace IS NULL 
           THEN 'test SAFEPLACE IS NULL' 
          ELSE 'test Safeplace IS NOT NULL' 
         END 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
         AND ot.trans_orderid = 5678 
       ), 
     middlename = (
        SELECT CASE 
           WHEN ot.safeplace IS NULL 
            THEN 'test SAFEPLACE IS NULL' 
           ELSE 'test Safeplace IS NOT NULL' 
          END 
         FROM order_transaction AS ot 
         WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ) 
WHERE customer.custid = 1234 
     AND EXISTS (
        SELECT * 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
       ); 

Khi cú pháp trông lặp lại, một trình tối ưu hóa tốt sẽ có thể nhận biết sự lặp lại và tối ưu hóa cho phù hợp. Cho dù phiên bản hiện tại của sản phẩm SQL của bạn thực sự làm tốt công việc tối ưu hóa điều này trong thực tế thì tất nhiên là một vấn đề khác. Nhưng hãy xem xét điều này: nếu sản phẩm SQL của bạn lựa chọn hỗ trợ cú pháp tiêu chuẩn nhưng không thực sự tối ưu hóa nó đúng là "hỗ trợ" có giá trị gì không?

Nếu bạn đang tìm cách sử dụng SQL chuẩn (như bạn thực sự cần IMO :) và muốn cú pháp "nhỏ gọn" hơn thì hãy xem MERGE hoặc MERGE (SQL) ví dụ: có thể trông giống như thế này:

MERGE INTO customer 
    USING (
      SELECT ot.custid, ot.forenames, 
       CASE 
        WHEN ot.safeplace IS NULL 
         THEN 'test SAFEPLACE IS NULL' 
        ELSE 'test Safeplace IS NOT NULL' 
        END 
      FROM order_transaction AS ot 
      WHERE ot.trans_orderid = 5678 
     ) AS source (custid, forenames, safeplace_narrative) 
    ON customer.custid = source.custid 
     AND customer.custid = 1234 
WHEN MATCHED THEN 
    UPDATE 
     SET forenames = source.forenames, 
      surname = source.safeplace_narrative, 
      middlename = source.safeplace_narrative; 
+0

@Richard aka cyberkiwi: cập nhật câu trả lời để thêm một ví dụ MERGE để hiển thị nó là nhỏ gọn hơn trong khi vẫn còn tiêu chuẩn SQL. – onedaywhen

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