Truy vấn để trả về tên cột đầu ra và kiểu dữ liệu của truy vấn, bảng hoặc dạng xem


21

Có một truy vấn hoặc lệnh PostgreSQL trả về tên trường và loại trường của truy vấn, bảng hoặc dạng xem không?

Ví dụ: một giải pháp nếu được áp dụng cho truy vấn CHỌN đơn giản như SELECT * from personsẽ trả về một danh sách như:

Column Name   | Column Type
===========================
First Name    | character
Last Name     | character
Age           | integer
Date of Birth | date

Tôi đã tìm kiếm các information_schemakhung nhìn được mô tả trong một câu trả lời dưới đây và nó dường như che phủ các bảng khá tốt và tôi nghi ngờ nó cũng bao gồm các khung nhìn nhưng tôi chưa kiểm tra điều đó.

Cuối cùng là bất kỳ truy vấn CHỌN tùy ý nhưng hợp lệ, ví dụ như liên quan JOINS, UNIONSv.v., trên cơ sở dữ liệu. Có một thủ tục tích hợp sẵn, hoặc các thủ tục hoặc tập lệnh được lưu trữ khác có thể trả lại giống nhau cho bất kỳ QUERY hợp lệ nào không?

Tôi đang phát triển một chương trình tạo dữ liệu và biểu mẫu truy vấn và thông tin là cần thiết để xác thực dữ liệu và thực thi các chức năng trên dữ liệu được trả về.


Rõ ràng không có "lệnh" nào, nhưng có nhiều cách khác nhau để lấy thông tin từ danh mục hệ thống. Vui lòng hỏi một câu hỏi cụ thể , thêm một ví dụ và những gì bạn mong đợi để đáp lại, và cho chúng tôi một ý tưởng về ý định đằng sau nó.
Erwin Brandstetter

1
Lý do cho sự đơn giản là vì khách hàng có liên quan đến các truy vấn tức là SELECTtruy vấn, tức là không xác định dữ liệu hoặc truy vấn thao tác dữ liệu, cho dù trên bảng, dạng xem hoặc các truy vấn khác trả về hàng và cột dữ liệu, do đó PostgreQuery có thể trả về danh sách các tên cột và kiểu dữ liệu của chúng. Các information_schemakhung nhìn được đề cập dưới đây trong các câu trả lời xuất hiện để trả lời nó cho các bảng và dạng xem. Các truy vấn CHỌN tùy ý là biên giới cuối cùng. Tôi sẽ chỉnh sửa câu trả lời để giải thích rõ hơn
vfclists

Câu trả lời:


22

Lược đồ thông tin so với danh mục hệ thống

Chúng tôi đã thảo luận về điều này nhiều lần. Các lược đồ thông tin phục vụ các mục đích nhất định. Nếu bạn biết cách của mình xung quanh các danh mục hệ thống, những mục đích đó phục vụ hầu hết các mục đích tốt hơn , IMO. Các danh mục hệ thống là nguồn thực tế của tất cả các thông tin.

Các giản đồ thông tin cung cấp được chuẩn hóa quan điểm mà giúp đỡ với tính di động, chủ yếu trên các phiên bản Postgres lớn, bởi vì tính di động trên nền tảng RDBMS khác nhau thường là một ảo tưởng một lần truy vấn của bạn có đủ tinh vi để cần phải nhìn lên catalog hệ thống. Và đáng chú ý, Oracle vẫn không hỗ trợ lược đồ thông tin.

Các khung nhìn trong lược đồ thông tin phải nhảy qua nhiều vòng để đạt được định dạng tuân theo tiêu chuẩn. Điều này làm cho chúng chậm, đôi khi rất chậm. So sánh các kế hoạch và hiệu suất cho các đối tượng cơ bản này:

EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;

Sự khác biệt là đáng chú ý. Nó thực sự phụ thuộc vào những gì bạn đang tìm kiếm.

Ví dụ của bạn

Ví dụ của bạn SELECT * from tbl, so sánh hai truy vấn dưới đây cho bảng đơn giản này:

CREATE TEMP TABLE foo(
   A numeric(12,3)
 , b timestamp(0)
);

Sử dụng pg_attribute:

SELECT attname, format_type(atttypid, atttypmod) AS type
FROM   pg_attribute
WHERE  attrelid = 'foo'::regclass
AND    attnum > 0
AND    NOT attisdropped
ORDER  BY attnum;

format_type() trả về kiểu hoàn chỉnh với tất cả các sửa đổi:

attname | type
--------+-------------------------------
a       | numeric(12,3)
b       | timestamp(0) without time zone

Cũng lưu ý rằng các diễn viên để regclassgiải quyết tên bảng một cách thông minh theo hiện tại search_path. Nó cũng đưa ra một ngoại lệ nếu tên không hợp lệ. Chi tiết:

Sử dụng information_schema.columns:

SELECT column_name, data_type
FROM   information_schema.columns
WHERE  table_name = 'foo'
ORDER  BY ordinal_position;

Thông tin được chuẩn hóa, nhưng không đầy đủ :

column_name | data_type
------------+----------------------------
a           | numeric
b           | timestamp without time zone

Để có được thông tin đầy đủ cho loại dữ liệu, bạn cần xem xét thêm tất cả các cột này:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Câu trả lời liên quan:

Danh sách ưu và nhược điểm , ưu điểm lớn nhất (IMO) được in đậm:

Chế độ xem lược đồ thông tin

  • thường đơn giản hơn (phụ thuộc)
  • chậm
  • tiền xử lý, có thể phù hợp hoặc không phù hợp với nhu cầu của bạn
  • chọn lọc (người dùng chỉ nhìn thấy các đối tượng họ có đặc quyền)
  • tuân thủ một tiêu chuẩn SQL (được triển khai bởi một số RDBMS chính)
  • chủ yếu là di động trên các phiên bản chính của Postgres
  • không đòi hỏi nhiều kiến ​​thức cụ thể về Postgres
  • định danh là mô tả, dài và đôi khi khó xử

Danh mục hệ thống

  • thường phức tạp hơn (phụ thuộc), gần với nguồn hơn
  • Nhanh
  • hoàn thành (cột hệ thống nhưoid bao gồm)
  • không tuân thủ tiêu chuẩn SQL
  • ít di động hơn trên các phiên bản Postgres chính (nhưng điều cơ bản sẽ không thay đổi)
  • đòi hỏi kiến ​​thức cụ thể hơn về Postgres
  • định danh là ngắn gọn, ít mô tả nhưng ngắn gọn thuận tiện

Truy vấn tùy ý

Để có cùng danh sách tên và kiểu cột từ một truy vấn, bạn có thể sử dụng một mẹo đơn giản: TẠO một bảng tạm thời từ đầu ra truy vấn, sau đó sử dụng các kỹ thuật tương tự như trên.

Bạn có thể nối thêm LIMIT 0, vì bạn không cần dữ liệu thực tế:

CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT  0;

Để lấy kiểu dữ liệu của các cột riêng lẻ, bạn cũng có thể sử dụng hàm pg_typeof():

SELECT pg_typeof(1);

Cảm ơn bạn rất nhiều. Tôi đã xem xét làm thế nào để có được kiểu dữ liệu của cột trong pg_attribution trong một thời gian và chỉ cần xem qua bài đăng này. Đánh giá cao bài viết của bạn.
Melinda

Nói chung, điều này hữu ích, nhưng không trả lời câu hỏi ban đầu về cách nhận thông tin về các loại dữ liệu của các cột mà câu lệnh SELECT cung cấp. Nó không phải là về các cột của các khung nhìn hoặc các bảng, tất nhiên nằm trong các danh mục hệ thống và cũng được hiển thị trong lược đồ thông tin.
Holger Jakobs

2

Bạn có thể sử dụng psqlmáy khách dòng lệnh.

\dt sẽ hiển thị một danh sách các bảng

\dv sẽ hiển thị một danh sách các quan điểm

\d [object_name] sẽ mô tả lược đồ của bảng hoặc dạng xem

Không chắc chắn làm thế nào bạn sẽ mô tả một truy vấn mặc dù.

Thông tin thêm: https://manikandanmv.wordpress.com/tag/basic-psql-commands/


2

Nếu bạn có quyền truy cập vào pg_catalog và sử dụng PGAdmin3, tôi rất khuyến nghị một giải pháp mà tôi tìm thấy trên blog của Valentine Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields. html ). Đó là một macro PGAdmin3 có thể được truy cập bằng một phím tắt để hiển thị định nghĩa của tên bảng đã chọn.

select quote_ident(nspname) || '.' || quote_ident(relname) as table_name, 
       quote_ident(attname) as field_name, 
       format_type(atttypid,atttypmod) as field_type, 
       case when attnotnull then ' NOT NULL' else '' end as null_constraint,
       case when atthasdef then 'DEFAULT ' || 
                                ( select pg_get_expr(adbin, attrelid) 
                                    from pg_attrdef 
                                   where adrelid = attrelid and adnum = attnum )::text else ''
       end as dafault_value,
       case when nullif(confrelid, 0) is not null
            then confrelid::regclass::text || '( ' || 
                 array_to_string( ARRAY( select quote_ident( fa.attname ) 
                                           from pg_attribute as fa 
                                          where fa.attnum = ANY ( confkey ) 
                                            and fa.attrelid = confrelid
                                          order by fa.attnum 
                                        ), ','
                                 ) || ' )'
            else '' end as references_to
  from pg_attribute 
       left outer join pg_constraint on conrelid = attrelid 
                                    and attnum = conkey[1] 
                                    and array_upper( conkey, 1 ) = 1,
       pg_class, 
       pg_namespace
 where pg_class.oid = attrelid
   and pg_namespace.oid = relnamespace
   and pg_class.oid = btrim( '$SELECTION$' )::regclass::oid
   and attnum > 0
   and not attisdropped
 order by attrelid, attnum;

Hoạt động như một sự quyến rũ và cực kỳ hữu ích.


1

Sử dụng các information_schemakhung nhìn , chúng là tiêu chuẩn SQL và chứa thông tin bạn muốn.

Bạn cũng có thể trực tiếp truy cập pg_class, pg_attribute, vv, nhưng đó là unportable và thường fiddlier; bạn có thể cần chức năng helper nhưoidvectortypes , pg_get_function_arguments, vv cho một số điều.

Nếu bạn muốn xem như thế nào psql thực thi một cái gì đó như thế nào \dt, hãy chạy psql -E- nó sẽ in truy vấn. Tuy nhiên, tốt hơn hết là sử dụng information_schemanếu nó sẽ đáp ứng nhu cầu của bạn.


1

Điều này có thể quá đơn giản, nhưng pgAdmin4 hiển thị các loại trường trong kết quả đầu ra. Các giải pháp khác ở trên có lẽ thanh lịch hơn, nhưng khi tôi chỉ cần một câu trả lời nhanh, tôi thấy GUI truy vấn của pgAdmin4 hoạt động khá tốt. Cố gắng tìm ra loại trường của một trường được tính toán được trả về bởi một khung nhìn hoặc hàm có thể khó khăn.

nhập mô tả hình ảnh ở đây


Thật tuyệt khi pgAdmin4 làm điều này, nhưng làm thế nào với nó? Chúng tôi có thể tìm hiểu mà không quét qua tất cả các mã nguồn của PGAdmin4 không?
Holger Jakobs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.