Truy vấn con là một cách hiệu quả để tìm dữ liệu bạn muốn sử dụng cho một truy vấn khác. Chúng thường được sử dụng trong các câu lệnh SELECT và UPDATE để làm cho các truy vấn này hiệu quả hơn và dễ bảo trì hơn.
Có một số cách khác nhau để sử dụng truy vấn con trong câu lệnh CẬP NHẬT. Chúng ta hãy xem xét từng người trong số họ.
SET và Subquery
Phương pháp đầu tiên chúng ta sẽ xem xét là sử dụng truy vấn con trong mệnh đề SET của câu lệnh UPDATE.
Giả sử chúng ta có một bảng các sản phẩm giống như sau:
[id bảng =29 /]
Nó lưu trữ một số thông tin về các sản phẩm khác nhau mà một công ty bán.
Giả sử rằng công ty quyết định tăng giá của sản phẩm "Couch" (id sản phẩm 1). Tuy nhiên, thay vì đặt một mức giá cụ thể, họ muốn đặt giá cao hơn 20% so với sản phẩm đắt nhất mà họ có.
Để làm điều này, chúng ta có thể sử dụng một truy vấn con trong mệnh đề SET. Chúng tôi có thể sử dụng các câu lệnh riêng biệt, nhưng sẽ dễ dàng hơn nếu sử dụng một câu lệnh duy nhất.
Tuyên bố của chúng tôi sẽ giống như sau:
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
Bạn có thể thấy rằng mệnh đề SET bao gồm một truy vấn con, tìm giá trị MAX của cột giá trong bảng sản phẩm và nhân nó với 1,2 để thêm 20%. Cuối cùng, mệnh đề WHERE nằm ngoài truy vấn con để chỉ cập nhật product_id của 1, vì nó áp dụng cho UPDATE chứ không phải cho truy vấn con.
Điều này sẽ dẫn đến thay đổi sau:
[id bảng =30 /]
SET và Truy vấn con có liên quan
Một cách khác để sử dụng truy vấn con trong câu lệnh UPDATE là sử dụng truy vấn con tương quan.
Nó hoạt động theo cách tương tự như ví dụ trước. Tuy nhiên, một truy vấn con tương quan là một truy vấn con tham chiếu đến câu lệnh bên ngoài và có thể là một phần của câu lệnh UPDATE.
Sử dụng dữ liệu từ ví dụ trước (bảng sản phẩm), công ty muốn hủy kích hoạt tất cả các sản phẩm chưa có đơn đặt hàng. Dữ liệu cho việc này được lưu trữ trong bảng order_line.
Nếu chúng tôi đã viết nó dưới dạng một truy vấn con tương quan, thì truy vấn sẽ giống như sau:
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
Truy vấn con sẽ thực hiện hàm COUNT bằng câu lệnh CASE để xác định xem giá trị trả về là Y hay N tùy thuộc vào giá trị của COUNT. Nó được tính toán cho mỗi product_id và khớp với truy vấn bên ngoài.
Điều này sẽ dẫn đến cột hoạt động cho một số sản phẩm được đặt thành Y và các sản phẩm khác được đặt thành N:
[id bảng =31 /]
Ở đâu lớn hơn truy vấn con
Cũng có thể sử dụng một truy vấn con trong mệnh đề WHERE. Cũng giống như trong các ví dụ trước, điều này có thể được thực hiện để loại bỏ bước riêng biệt là tìm kiếm giá trị cần cập nhật và sau đó chạy truy vấn để cập nhật giá trị đó.
Chúng tôi có thể tiếp tục làm việc với ví dụ của chúng tôi từ các bước trước. Giả sử rằng công ty muốn kích hoạt các sản phẩm có giá trên mức trung bình. Để làm điều này, chúng ta có thể thêm một truy vấn con vào mệnh đề WHERE.
Trước tiên, hãy hủy kích hoạt tất cả các sản phẩm.
UPDATE product SET active = ’N’;
Sau đó, cập nhật bảng bằng truy vấn con của chúng tôi.
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
Điều này sẽ đặt giá trị hiện hoạt thành Y cho tất cả các bản ghi có giá trên trung bình.
Bảng bây giờ trông giống như sau:
[id bảng =32 /]
Nó hiển thị 2 bản ghi có giá trị đang hoạt động là Y vì chúng ở trên mức trung bình.
Loại truy vấn này cũng có thể được chạy với các toán tử khác cho phép một giá trị duy nhất, chẳng hạn như
WHERE TRONG Truy vấn con
Ngoài ra, chúng ta có thể sử dụng truy vấn con với toán tử IN trong mệnh đề WHERE.
Điều này tương tự với ví dụ trước đã sử dụng toán tử lớn hơn cho một giá trị duy nhất. Toán tử IN có thể được áp dụng cho nhiều giá trị.
Giả sử công ty muốn cập nhật giá của một số sản phẩm là mặt hàng duy nhất trong danh mục. Giá sẽ cần phải giảm một nửa.
Truy vấn của chúng tôi có thể trông giống như sau:
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
Truy vấn con tìm tất cả các giá trị category_id trong đó COUNT là 1. Chúng tôi không cần phải có COUNT trong phần CHỌN của truy vấn con, tuy nhiên, nếu có, truy vấn sẽ hiển thị lỗi.
Câu lệnh UPDATE sẽ cập nhật giá mà danh mục đáp ứng tiêu chí của truy vấn con.
Kết quả của chúng tôi sau đó sẽ như thế này:
[id bảng =33 /]
Dữ liệu trông rất giống nhau. Tuy nhiên, sản phẩm có ID danh mục là 1 đã được cập nhật giá thành một nửa giá gốc vì đây là sản phẩm duy nhất trong danh mục đó.
CẬP NHẬT Truy vấn con
Cuối cùng, bạn có thể sử dụng truy vấn con trong câu lệnh UPDATE để cập nhật bảng.
Trong các ví dụ trước, chúng ta chỉ sử dụng bảng sản phẩm. Tuy nhiên, bạn có thể sử dụng truy vấn con thay vì bảng sản phẩm, truy vấn này sẽ trả về tập kết quả có thể được cập nhật.
Tập kết quả cần phải được cập nhật, tương tự như trường hợp khi bạn tạo một đối tượng VIEW và cố gắng cập nhật nó. Nó phải đơn giản và có khóa chính.
Do đó, sử dụng các ví dụ trước đây của chúng tôi, giả sử rằng công ty muốn thay đổi danh mục cho tất cả các sản phẩm thuộc danh mục 4 thành danh mục 5.
Truy vấn của chúng tôi có thể trông giống như sau:
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
Đó là một ví dụ đơn giản thể hiện khái niệm này. Bảng đã được thay thế bằng câu lệnh SELECT chỉ hiển thị hai cột của bảng.
Kết quả của truy vấn này sẽ là:
[id bảng =34 /]
Kết quả tương tự có thể nhận được bằng cách chuyển mệnh đề WHERE sang câu lệnh UPDATE:
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
Kết luận
Sử dụng truy vấn con trong câu lệnh UPDATE có thể là một cách tốt để cải thiện khả năng duy trì các truy vấn của bạn. Nó cũng có thể giảm số bước cần thiết để cập nhật dữ liệu của bạn bằng cách nén hai hoặc nhiều truy vấn thành một truy vấn duy nhất.