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

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?

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

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

Вы можете использовать psqlклиент командной строки.

\dt покажет список таблиц

\dv покажет список просмотров

\d [object_name] опишу схему таблицы или вида

Не уверен, как бы вы описали запрос.

Дополнительная информация: https://manikandanmv.wordpress.com/tag/basic-psql-commands/

Нил Макгиган
источник
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?
Хольгер Джейкобс