Запрос на возврат имен выходных столбцов и типов данных запроса, таблицы или представления


21

Существует ли запрос или команда PostgreSQL, которая возвращает имена полей и типы полей запроса, таблицы или представления?

Например, решение, если оно применяется к простому запросу SELECT, SELECT * from personдолжно возвращать список вроде:

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

Я просмотрел information_schemaпредставления, описанные в ответе ниже, и, кажется, он достаточно хорошо охватывает таблицы, и я подозреваю, что он также охватывает и представления, но я еще не проверял это.

Последним является любой произвольный, но действительный запрос SELECT, например, включающий JOINSи UNIONSт. Д. В базу данных. Существует ли встроенная процедура или другая хранимая процедура или сценарий, которые могут возвращать то же самое для любого действительного запроса QUERY?

Я разрабатываю программу, которая создает данные и запрашивает формы, и эта информация необходима для проверки данных и выполнения функций для возвращаемых данных.


Очевидно, что не существует единой «команды», но существуют различные способы получения информации из системных каталогов. Пожалуйста, задайте конкретный вопрос , добавьте пример и то, что вы ожидаете взамен, и дайте нам представление о намерении, стоящем за ним.
Эрвин Брандстеттер

1
Причина простоты заключается в том, что в отношении клиентов запросы, т. SELECTЕ. Запросы, то есть запросы, не определяющие данные или манипулирующие данными, будь то таблицы, представления или другие запросы, возвращают строки и столбцы данных, поэтому PostgreSQL должен иметь возможность возвращать список имен столбцов и их типов данных. Представления, information_schemaупомянутые ниже в ответах, по-видимому, отвечают за таблицы и представления. Произвольные запросы SELECT являются последней границей. Я отредактирую ответ, чтобы объяснить лучше
vfclists

Ответы:


22

Информационная схема и системные каталоги

Мы много раз обсуждали это. Информационная схема служит определенным целям. Если вы знакомы с системными каталогами, то они лучше всего подходят для большинства целей , IMO. Системные каталоги являются актуальным источником всей информации.

Информация схема обеспечивает стандартизированное мнение , которые помогают с мобильностью, в основном через крупную Postgres версию, потому что портативность на разные платформах RDBMS , как правило , является иллюзией , как только ваши запросы достаточно сложные для необходимости искать системные каталоги. И, в частности, Oracle все еще не поддерживает информационную схему.

Представления в информационной схеме должны перепрыгивать через множество циклов, чтобы получить формат, соответствующий стандарту. Это делает их медленными, иногда очень медленными. Сравните планы и производительность для этих основных объектов:

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

Разница замечательная. Это действительно зависит от того, что вы ищете.

Ваш пример

Для вашего примера SELECT * from tblсравните два запроса ниже для этой простой таблицы:

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

Использование 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() возвращает полный тип со всеми модификаторами:

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

Также обратите внимание, что приведение к regclassразрешает имя таблицы несколько разумно в соответствии с текущим search_path. Это также вызывает исключение, если имя недействительно. Детали:

Использование information_schema.columns:

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

Информация стандартизирована, но неполна :

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

Чтобы получить полную информацию о типе данных, вам необходимо дополнительно рассмотреть все эти столбцы:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Связанные ответы:

Список плюсов и минусов , самые большие плюсы (ИМО) выделены жирным шрифтом:

Представления информационной схемы

  • часто проще (зависит)
  • медленный
  • предварительно обработанный, который может или не может удовлетворить ваши потребности
  • выборочный (пользователи видят только те объекты, для которых у них есть привилегии)
  • соответствует стандарту SQL (который реализуется некоторыми основными СУБД)
  • в основном портативные через основные версии Postgres
  • не требуют особых знаний о Postgres
  • идентификаторы описательные, длинные и иногда неудобные

Системные каталоги

  • часто более сложный (зависит), ближе к источнику
  • быстро
  • полный (системные столбцы, как oidвключены)
  • не соответствует стандарту SQL
  • менее переносимый среди основных версий Postgres (но основы не изменится)
  • требуют более конкретных знаний о Postgres
  • идентификаторы краткие, менее описательные, но удобно короткие

Произвольный запрос

Чтобы получить тот же список имен и типов столбцов из запроса, вы можете использовать простой прием: СОЗДАЙТЕ временную таблицу из результатов запроса, а затем используйте те же методы, что и выше.

Вы можете добавить LIMIT 0, так как вам не нужны фактические данные:

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

Чтобы получить тип данных отдельных столбцов, вы также можете использовать функцию pg_typeof():

SELECT pg_typeof(1);

Огромное спасибо. Я некоторое время смотрел, как получить тип данных столбца в pg_attribute, и только что наткнулся на этот пост. Цените свой пост.
Мелинда

В целом это полезно, но не отвечает на первоначальный вопрос о том, как получить информацию о типах данных столбцов, которые предоставляет оператор SELECT. Речь шла не о столбцах представлений или таблиц, которые, конечно, находятся в системных каталогах и также отображаются в информационной схеме.
Хольгер Джейкобс


2

Если у вас есть доступ к pg_catalog и вы используете PgAdmin3, я настоятельно рекомендую решение, которое я нашел в техническом блоге Валентина ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields). HTML ). Это макрос PgAdmin3, к которому можно получить доступ с помощью ярлыка для отображения определения выбранного имени таблицы.

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;

Работает как шарм и очень полезно.


1

Используйте те information_schemaвзгляды , они SQL-стандарт и содержат информацию , которую вы хотите.

Вы также можете получить прямой доступ pg_classи pg_attributeт. Д., Но это непереносимо и часто неудобно; вам могут понадобиться вспомогательные функции, такие какoidvectortypes , pg_get_function_argumentsи т. д. для некоторых вещей.

Если вы хотите увидеть, как psqlвыполняется что-то вроде \dt, запустите psql -E- он напечатает запрос. Тем не менее, обычно лучше использовать, information_schemaесли он будет соответствовать вашим потребностям.


1

Это может быть слишком просто, но pgAdmin4 показывает типы полей в выходных результатах. Другие решения выше, вероятно, более элегантны, но когда мне просто нужен быстрый ответ, я нахожу, что графический интерфейс запроса pgAdmin4 работает довольно хорошо. Попытка выяснить тип поля вычисляемого поля, возвращаемого представлением или функцией, может быть сложной.

введите описание изображения здесь


Это очень хорошо, что pgAdmin4 делает это, но как это с ним? Можем ли мы узнать без сканирования весь исходный код PgAdmin4?
Хольгер Джейкобс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.