Nó phụ thuộc vào những gì bạn muốn kiểm tra chính xác .
Lược đồ thông tin?
Để tìm "liệu bảng có tồn tại không" ( bất kể ai hỏi ), truy vấn lược đồ thông tin ( information_schema.tables
) là không chính xác , nói đúng, bởi vì ( theo tài liệu ):
Chỉ những bảng và chế độ xem được hiển thị rằng người dùng hiện tại có quyền truy cập (bằng cách là chủ sở hữu hoặc có một số đặc quyền).
Truy vấn được cung cấp bởi @kong có thể trả về FALSE
, nhưng bảng vẫn có thể tồn tại. Nó trả lời câu hỏi:
Làm cách nào để kiểm tra xem bảng (hoặc dạng xem) có tồn tại không và người dùng hiện tại có quyền truy cập vào bảng không?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Lược đồ thông tin chủ yếu hữu ích để duy trì khả năng di động trên các phiên bản chính và trên các RDBMS khác nhau. Nhưng việc triển khai còn chậm, vì Postgres phải sử dụng các quan điểm tinh vi để tuân thủ tiêu chuẩn ( information_schema.tables
là một ví dụ khá đơn giản). Và một số thông tin (như OID) bị mất trong bản dịch từ danh mục hệ thống - mà thực sự mang tất cả thông tin.
Danh mục hệ thống
Câu hỏi của bạn là:
Làm thế nào để kiểm tra xem một bảng có tồn tại?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
AND c.relkind = 'r' -- only tables
);
Sử dụng các danh mục hệ thống pg_class
và pg_namespace
trực tiếp, cũng nhanh hơn đáng kể. Tuy nhiên, mỗi tài liệu vềpg_class
:
Các danh mục pg_class
danh mục bảng và hầu hết mọi thứ khác có cột hoặc tương tự như bảng. Điều này bao gồm các chỉ mục (nhưng cũng xem pg_index
), trình tự , khung nhìn , khung nhìn cụ thể hóa , kiểu tổng hợp và bảng TOAST ;
Đối với câu hỏi cụ thể này, bạn cũng có thể sử dụng chế độ xem hệ thốngpg_tables
. Một chút đơn giản và dễ mang theo hơn trên các phiên bản Postgres chính (điều này hầu như không đáng quan tâm đối với truy vấn cơ bản này):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Định danh phải là duy nhất trong số tất cả các đối tượng được đề cập ở trên. Nếu bạn muốn hỏi:
Làm thế nào để kiểm tra xem tên của một bảng hoặc đối tượng tương tự trong một lược đồ đã cho có được thực hiện không?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
);
Thay thế: chuyển sang regclass
SELECT 'schema_name.table_name'::regclass
Điều này đặt ra một ngoại lệ nếu bảng (tùy chọn đủ điều kiện lược đồ) (hoặc đối tượng khác chiếm tên đó) không tồn tại.
Nếu bạn không đủ điều kiện lược đồ tên bảng, thì một giá trị regclass
mặc định cho search_path
và trả về OID cho bảng đầu tiên được tìm thấy - hoặc một ngoại lệ nếu bảng không nằm trong các lược đồ được liệt kê. Lưu ý rằng các lược đồ hệ thống pg_catalog
và pg_temp
(lược đồ cho các đối tượng tạm thời của phiên hiện tại) tự động là một phần của search_path
.
Bạn có thể sử dụng và bắt một ngoại lệ có thể có trong một hàm. Thí dụ:
Một truy vấn như trên tránh được các ngoại lệ có thể xảy ra và do đó nhanh hơn một chút.
Bây giờ đơn giản hơn nhiều:
SELECT to_regclass('schema_name.table_name');
Giống như các diễn viên, nhưng nó trở lại ...
... null thay vì ném lỗi nếu không tìm thấy tên
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]