Запит для повернення вихідних назв стовпців та типів даних запиту, таблиці чи представлення


21

Чи є запит або команда PostgreSQL, яка повертає назви полів та типи полів запиту, таблиці чи представлення?

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

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

Я переглянув information_schemaпогляди, описані у відповіді нижче, і, здається, досить добре покриває таблиці, і я підозрюю, що він також охоплює погляди, але ще не перевіряв цього.

Останнім є довільним , але діє ВИБРАТИ запит , наприклад , з участю, JOINS, і UNIONSт.д., в базі даних. Чи є вбудована процедура чи інша збережена процедура чи сценарій, які взагалі можуть повернути те саме для будь-якого дійсного ЗАПИТУ?

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


Очевидно, що немає єдиної "команди", але існують різні способи отримання інформації з системних каталогів. Будь ласка, задайте конкретне запитання , додайте приклад і те, що ви очікуєте взамін, і дайте нам уявлення про наміри, що стоять за ним.
Erwin Brandstetter

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

Відповідні відповіді:

Список плюсів і мінусів , найбільші плюси (IMO), виділені жирним шрифтом:

Перегляди інформаційної схеми

  • часто простіше (залежить)
  • повільний
  • попередньо оброблена, що може відповідати вашим потребам
  • вибірковий (користувачі бачать лише об'єкти, на які мають привілеї)
  • відповідність стандарту SQL (це реалізовано деякими основними RDBMS)
  • в основному портативні в основних версіях 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, я настійно рекомендую рішення, яке я знайшов у блозі Valentine's Tech ( 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і т.д., але це переносяться і часто fiddlier; Вам може знадобитися допоміжні функції , такі як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.