PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

quote_ident() n'ajoute pas de guillemets au nom de la colonne en premier

N'omettez pas AS mot clé pour les alias de colonne

Pas exactement. Il explose parce que vous avez omis le mot-clé AS où il ne doit pas être omis.

Cela fonctionne :

SELECT 'select ' 
|| string_agg(
        case when udt_name in ('varchar', 'text')
            then 'left(' || quote_ident(column_name) || ', 65535) AS '  -- !!
              ||  quote_ident(column_name)
        else quote_ident(column_name)
        end, ', ' order by ordinal_position) 
|| ' from "public"."MyTableName"'
FROM information_schema.columns c
join parse_ident('"public"."MyTableName"') t 
on t[1] = table_schema and t[2] = table_name;

Produit :

SELECT id, left(first, 65535) AS first from "public"."MyTableName";

Qui fonctionne comme prévu à son tour.

Le manuel sur "Omettre le COMME Mot clé" :

Vous pouvez omettre le mot-clé AS pour les alias de table, mais pas pour les alias de colonne.

first n'est pas un mot réservé dans Postgres. (Il était "réservé" dans l'ancien standard SQL SQL-92, mais plus dans le SQL standard non plus.) Il est "non réservé" * pour être précis. Le manuel :

Omettre AS en fait un tel contexte.

quote_ident() fonctionne de manière fiable. Le manuel :

format() avec le spécificateur %I fait de même.

Les mots réservés ne sont pas mentionnés, mais cités correctement malgré tout. Pour être précis :tous les mots clés marqués "réservés" ou "(ne peut pas être une fonction ou un type)" dans la colonne "PostgreSQL" de le Mots clés SQL tableau .

Je vais déposer un bogue de documentation pour ajouter cela.

Pour être absolument sûr :quote_all_identifiers

Si vous voulez être absolument sûr et que tout le bruit supplémentaire ne vous dérange pas, vous pouvez forcer Postgres à citer tous identifiants avec le paramètre de configuration quote_all_identifiers . Le manuel :

Cela inclut la sortie de quote_ident() et format() . Je ne le ferais pas faites-le, redoutant tout le bruit supplémentaire.

Vous pouvez définir le paramètre localement avec SET LOCAL dans la même opération. Comme :

BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;

Plus rapide

Cela dit, j'utiliserais format() et concat() et ciblez la table catalogue pg_attribute au lieu de cela :plus propre, plus simple, plus rapide. Mais pas portable vers d'autres RDBMS :

SELECT format('SELECT %s FROM %s;'
            , string_agg(CASE WHEN atttypid = ANY ('{text, bpchar, varchar}'::regtype[])
                              THEN concat('left(', col, ', 65535) AS ', col)
                              ELSE col END, ', ')
            , attrelid)
FROM  (
   SELECT attrelid::regclass, atttypid, quote_ident(attname) AS col
   FROM   pg_catalog.pg_attribute
   WHERE  attrelid = 'public."MyTableName"'::regclass  -- provide once, optionally schema-qualified
   AND    attnum > 0
   AND    NOT attisdropped
   ORDER  BY attnum
   ) sub
GROUP  BY attrelid;

Produit :

SELECT id, left(first, 65535) AS first FROM "MyTableName";

db<>violon ici

Notamment, ...

  • ... vous n'avez besoin de fournir le nom de la table qu'une seule fois, éventuellement qualifié par le schéma.
  • ... si la table n'existe pas, la requête échoue immédiatement avec un message d'erreur utile.
  • ... le nom de la table de sortie est uniquement qualifié par le schéma et entre guillemets si nécessaire.
  • ... ceci couvre également le character(N) (nom interne bpchar ).

Lectures complémentaires :