web-dev-qa-db-fra.com

ERREUR: Impossible de trouver le type de tableau pour le type de données INFORMATION_SCHEMA.SQL_Identififier

J'essaie d'exécuter la commande SQL ci-dessous:

SELECT ARRAY(
    SELECT column_name 
    FROM information_schema.columns 
    WHERE table_name ='gis_field_configuration_stage'
);

et je reçois l'erreur ci-dessous:

ERROR:  could not find array type for datatype information_schema.sql_identifier
3
John Mitchell

Juste jeter column_name à text pour contourner l'erreur:

SELECT ARRAY(
    SELECT column_name::text
    FROM information_schema.columns 
    WHERE table_name ='gis_field_configuration_stage'
);

Son type d'origine est information_schema.sql_identifier Et son arrive qu'un tableau de ce type n'est pas fourni dans les types prédéfinis.

6
Daniel Vérité

Un nom de table n'est pas unique

Un nom de table est pas Un identifiant unique. Un tableau du même nom pourrait exister dans un autre schéma.

Cela peut fonctionner très bien pour utiliser des noms de table dans vos questions sans schéma - les qualifier. Tant que votre search_path est défini correctement, les bonnes tables seront cueillies.

Mais cela ne vous aidera pas à interroger des tables de catalogue! Si d'autres tables du même nom existent, vous récupérez toutes les colonnes de toutes ces tables et que vous ne le remarquerez même pas. Ajoutez le nom du schéma pour le rendre unique:

SELECT ARRAY(
   SELECT column_name::text
   FROM   information_schema.columns 
   WHERE  table_name ='gis_field_configuration_stage'
   AND    table_schema ='public'  -- or whatever the schema is
)

information_schema est lent

information_schema est seulement bon pour la portabilité des plats de plâtre (qui ne fonctionne presque jamais de toute façon). La vue dans information_schema sont monstrueux et lents. Si vous n'avez pas l'intention de le porter sur un autre RDBMS dans le futur, et si vous n'utilisez pas de fonctionnalités exotiques susceptibles de changer entre les versGRES, l'utilisation pg_catalog.pg_attribute à la place. Postgres est pas Va changer pg_attribute D'une manière qui invaliderait cette requête équivalente:

SELECT ARRAY(
   SELECT attname
   FROM   pg_catalog.pg_attribute
   WHERE  attrelid = 'public.tbl'::regclass
   AND    NOT attisdropped
   AND    attnum > 0
);

Autour 100 fois Plus vite dans mes tests.

La coulée à regclass est sûr

Cela a un autre avantage important: si vous en erreur un nom de table ou que cela n'existe pas pour une autre raison de la première requête, il ne trouvera pas de colonnes. Le résultat peut être trompeur et vous ne le saurez jamais. Si vous lancez la table comme si je démontre ('public.tbl'::regclass), vous obtenez un message d'erreur si le tableau ne doit pas exister. plus sur les types d'identifiant d'objet dans le manuel.

Vous pourriez même utiliser 'tbl'::regclass, parce que le search_path est utilisé pour l'évaluation de cette expression. Si votre requête de base fonctionne sans qualification de schéma, cela aussi. Il est toujours plus sûr d'ajouter le schéma.

En rapport:

Query invalide

L'approche de votre commentaire est invalide pour commencer par.
[.____] ARRAY[...] NOT IN ARRAY[...] n'a pas de sens à Postgres.

Si vous voulez vous assurer que deux tables ne partagent pas tout Noms de colonne :

SELECT *
FROM   tbl
WHERE  NOT EXISTS (
   SELECT 1
   FROM   pg_catalog.pg_attribute a1
   JOIN   pg_catalog.pg_attribute a2 USING (attname)
   WHERE  a1.attrelid = 'public.tbl'::regclass
   AND    NOT a1.attisdropped
   AND    a1.attnum > 0
   AND    a2.attrelid = 'public.tbl2'::regclass
   AND    NOT a2.attisdropped
   AND    a2.attnum > 0
   );

Si vous voulez vous assurer que deux tables ne partagent pas tout leurs noms de colonne :

SELECT *
FROM   tbl
WHERE  EXISTS (
   SELECT 1
   FROM   (
      SELECT attname
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = 'public.tbl'::regclass
      AND    NOT attisdropped
      AND    attnum > 0
      ) a1
   FULL   OUTER JOIN (
      SELECT attname
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = 'public.tbl2'::regclass
      AND    NOT attisdropped
      AND    attnum > 0
      ) a2 USING (attname)
   WHERE  a1.attname IS NULL OR
          a2.attname IS NULL
   );
4
Erwin Brandstetter