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 internebpchar
).
Lectures complémentaires :
- Comment vérifier si une table existe dans un schéma donné
- Tronquer l'affichage par défaut dans les instructions postgres psql select
- PostgreSQL force les majuscules pour toutes les données
- Vérifier si des chaînes vides sont présentes dans les colonnes de type caractère