PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Các truy vấn kiểu CHỌN có phải là kiểu duy nhất có thể được lồng vào nhau không?

Câu trả lời cơ bản

CTE (Biểu thức bảng chung) trong Postgres (giống như trong bất kỳ RDBMS hiện đại chính nào ngoại trừ MySQL). Kể từ phiên bản 9.1 bao gồm các CTE sửa đổi dữ liệu. Chúng có thể được "lồng vào nhau".
Cập nhật:MySQL 8.0 cuối cùng đã thêm CTE.

Không giống như truy vấn phụ CTE đặt ra như những rào cản tối ưu hóa. Trình lập kế hoạch truy vấn không thể nội dòng các lệnh tầm thường vào lệnh chính hoặc sắp xếp lại các phép nối giữa các truy vấn chính và CTE. Điều này cũng có thể xảy ra với các truy vấn con. Có thể (rất) tốt hoặc (rất) kém đối với hiệu suất, điều đó phụ thuộc vào.
Dù bằng cách nào, CTE cũng yêu cầu chi phí (chi phí hiệu suất) cao hơn một chút so với truy vấn con.
Cập nhật:Postgres 12 cuối cùng có thể nội tuyến CTE đơn giản trong truy vấn chính.

Chi tiết bạn không yêu cầu

Câu hỏi của bạn rất cơ bản, trên đây chắc cũng đủ trả lời. Nhưng tôi sẽ thêm một chút cho người dùng nâng cao (và một ví dụ mã để hiển thị cú pháp).

Tất cả các CTE của truy vấn đều dựa trên cùng một ảnh chụp nhanh của cơ sở dữ liệu. CTE tiếp theo có thể sử dụng lại đầu ra của các CTE trước đó (bảng tạm thời nội bộ), nhưng ảnh hưởng trên các bảng bên dưới là vô hình đối với các CTE khác. Trình tự của nhiều CTE là tùy ý trừ khi một cái gì đó được trả lại bằng RETURNING mệnh đề cho INSERT , UPDATE , DELETE - không liên quan cho SELECT , vì nó không thay đổi bất cứ điều gì và chỉ đọc từ ảnh chụp nhanh.

Điều đó có thể có những tác động tinh tế với nhiều bản cập nhật sẽ ảnh hưởng đến cùng một hàng. Chỉ một cập nhật có thể ảnh hưởng đến từng hàng. Cái nào bị ảnh hưởng bởi chuỗi CTE.

Cố gắng dự đoán kết quả:

CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');

WITH sel AS (SELECT * FROM t)
   , up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
   , up2 AS (UPDATE t SET txt = t.txt || '2'
             FROM   up1
             WHERE  up1.t_id = t.t_id
             RETURNING t.*)
   , ins AS (INSERT INTO t VALUES (4, 'bamm'))
   , up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't'   AS source, * FROM t;

SQL Fiddle

Đừng thất vọng, tôi nghi ngờ có nhiều người ở đây có thể đã làm được điều đó. :)
Ý chính của điều này: tránh các lệnh xung đột trong CTE.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Không thể kết nối với PostgreSQL bằng PHP pg_connect ()

  2. Khắc phục:“không tồn tại toán tử:integer || số nguyên ”trong PostgreSQL

  3. 8 tính năng tương thích mới của Oracle trong EnterpriseDB PPAS 9.2 Beta

  4. Tính toán tỷ lệ phần trăm với truy vấn GROUP BY

  5. Cách UNION hoạt động trong PostgreSQL