PostgreSQL v9.X имеет реальный массив записей?

Этот запрос работает нормально,

 WITH test AS (
   SELECT array_agg(t) as x FROM (
     SELECT 1111 as id, 'aaaaa' as cc  
   ) AS t
 ) SELECT x[1] FROM test;

но, могу ли я получить доступ к элементам записи? Я пытаюсь SELECT x[1].id; SELECT x[1][1]; ... ничего не работает.

PS: с Google мы видим только СТАРЫЕ решения ... Контекст здесь v9.X, нет новостей о "массиве записей"?


Я тоже стараюсь

 select x[1] from (select array[row(1,2)] as x) as t;

нет решения для доступа только к элементу 1 или только к элементу 2.


Подсказка, которую я не смог понять: postgresql.1045698.n5.nabble.com Решите проблему с помощью _5 _... Хорошо, но мне нужно решение "все в запросе". Где «динамическая типизация» PostgreSQL ?? Как выполнить CAST или выразить тип без предложения CREATE TYPE?


person Peter Krauss    schedule 20.01.2014    source источник
comment
Вы можете преобразовать значение в hstore и таким образом извлечь из него поля, но это не совсем то, что вам нужно. Псевдотип PostgreSQL record немного ограничен - в частности, нет анонимного приведения записей, например CAST(somerecord AS t(x integer, y text)) не работает.   -  person Craig Ringer    schedule 21.01.2014
comment
Кстати, если это то, что вы хотите, вам нужно поднять шум об этом и, вероятно, подкрепить этот шум готовностью выполнять реальную работу и / или вносить свой вклад в время разработки. Это своего рода уголок системы типов, и никто особо не заинтересован в работе над ним, поэтому вам нужно достаточно заботиться, чтобы это произошло самостоятельно, или найти способы заставить других достаточно заботиться о том, чтобы справиться с этим.   -  person Craig Ringer    schedule 21.01.2014
comment
У вас есть для этого больше контекста? Возможно, есть другой способ попасть туда, где вам нужно быть.   -  person mu is too short    schedule 21.01.2014
comment
Извините @Mu, нам не нужно больше контекста, это синтаксическое противоречие PostgreSQL ... Я думаю, что Крейг подтверждает мой обман с помощью pg9.X: нет новостей.   -  person Peter Krauss    schedule 21.01.2014
comment
Спасибо @CraigRinger, вы понимаете мои уловки и показываете лучшее название: анонимное приведение записей - это отсутствие синтаксиса PG. Именно это я и искал при построении такого рода запросов. PostgreSQL позволяет выразить то, что кажется Array of Recortd, но разочаровывает нас на полпути ... Да, мне нужно пошуметь о многих мелочах, но, возможно, первый шум - это Здравствуйте, PG-Community! Мы в 2014 году! Где сайт RFC? Где интерфейс для Заинтересованного лица для голосования! ??   -  person Peter Krauss    schedule 21.01.2014
comment
@PeterKrauss Это открытый исходный код. Вы являетесь заинтересованным лицом, если вносите свой вклад - будь то помощь людям в списках или здесь, подробный дизайн, поиск ошибок и отчетность, исправление ошибок, очистка кода, добавление функций, обзор исправлений и т. Д. И т. Д. Я предлагаю принять участие и внести свой вклад, если вы хочу быть услышанным. (Также, пожалуйста, не говорите, что 9.x - 9.0, 9.1, 9.2, ... все основные выпуски. Да, это глупо, но мы застряли на этом). Вы заботитесь об этом - другие заботятся о двунаправленной репликации, другие о безопасности на уровне строк и мультитенантности, ... Шуметь, быть услышанным, вносить свой вклад.   -  person Craig Ringer    schedule 21.01.2014


Ответы (1)


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

У вас есть три варианта обхода:

  • CREATE TYPE
  • hstore

CREATE TYPE

Проблема с записями анонимного типа. Так что сделайте это не анонимным. К сожалению, это возможно только до того, как запись станет анонимным; в настоящее время вы не можете преобразовать record в тип пользователя. Итак, вам нужно сделать:

CREATE TYPE some_t AS (id integer, cc text);

WITH test AS (
   SELECT array_agg(t::some_t) as x FROM (
     SELECT 1111 as id, 'aaaaa' as cc  
   ) AS t
 ) SELECT x[1].id FROM test;

Обратите внимание на приведение вывода подзапроса к some_t перед агрегированием.

Я не могу сказать, что понимаю, почему это приведение не может быть выполнено после индексации массива.

hstore

Как обычно, hstore приходит на помощь, когда решает сложные типовые задачи.

regress=> WITH test AS (
       SELECT array_agg(t) as x FROM (
         SELECT 1111 as id,  'aaaaa' as cc  
       ) AS t
     ) SELECT hstore(x[1])->'id' FROM test;
 ?column? 
----------
 1111
(1 row)

Вам нужно расширение hstore, и я уверен, что оно неэффективно, но работает. Это основано на hstore поддержке создания hstore из анонимных записей, которые были добавлены для поддержки NEW и OLD в триггерах, что было проблемой в прошлом.

Функция обертки?

Оказывается, вы не можете обойти это с помощью простой функции-оболочки, позволяющей указать тип на сайте вызова:

regress=> CREATE OR REPLACE FUNCTION identity(record) RETURNS record AS $$
          SELECT $1; 
          $$ LANGUAGE sql IMMUTABLE;
ERROR:  SQL functions cannot have arguments of type record

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

Сделать лучше?

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

Должна быть возможность сделать так, чтобы PostgreSQL поддерживал что-то вроде:

WITH test AS (
   SELECT array_agg(t) as x FROM (
      SELECT 1111 as id,  'aaaaa' as cc  
   ) AS t
) SELECT (x[1] AS some_t(id integer, cc text)).id  FROM test;

это просто потребовало бы соответствующего взлома парсера и способа гарантировать, что он никогда не будет неоднозначно проанализирован в конфликте с псевдонимом столбца.

На самом деле, даже вывод типов мог бы быть возможен, если бы кто-то был готов вложить эту работу и убедить команду в том, что довольно большое количество требуемого времени процессора планировщика запросов того стоит. (вряд ли).

Это раздражающий, но второстепенный момент в системе шрифтов. Если вы хотите, чтобы это изменилось, вам нужно будет пошуметь над pgsql-general и сопровождать этот шум готовностью проделать реальную работу по устранению проблемы. Это может включать в себя изучение внутренней сущности системы типов PostgreSQL больше, чем вы когда-либо хотели, изучение удовольствия от «обратной совместимости» и ведение разочаровывающих споров вокруг и вокруг. Добро пожаловать в открытый исходный код!

person Craig Ringer    schedule 21.01.2014