No omita AS
palabra clave para alias de columna
No exactamente. Explota porque omitió la palabra clave AS
donde no debe omitirse.
Esto funciona:
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;
Produce:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Que funciona como se esperaba a su vez.
El manual sobre "Omitir el COMO palabra clave" :
Está bien omitir la palabra clave AS
para alias de tabla, pero no para alias de columna.
first
no es una palabra reservada
en Postgres. (Solía estar "reservado" en el antiguo SQL estándar SQL-92, pero ya no en SQL estándar). Es "no reservado" * para ser preciso. El manual
:
Omitiendo AS
lo convierte en tal contexto.
quote_ident()
funciona de manera confiable. El manual:
format()
con el especificador %I
hace lo mismo.
Las palabras reservadas no se mencionan, pero se citan correctamente independientemente. Para ser precisos:todas las palabras clave marcadas "reservadas" o "(no puede ser función ni tipo)" en la columna "PostgreSQL" de la Palabras clave de SQL mesa .
Archivaré un error de documentación para agregar eso.
Para estar absolutamente seguro:quote_all_identifiers
Si quiere estar absolutamente seguro y no le importa todo el ruido agregado, puede obligar a Postgres a citar todo identificadores con el parámetro de configuración quote_all_identifiers
. El manual:
Eso incluye la salida de quote_ident()
y format()
. Yo no haz eso, temiendo todo el ruido adicional.
Puede establecer el parámetro localmente con SET LOCAL
en la misma transacción. Me gusta:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Más rápido
Dicho esto, usaría format()
y concat()
y apunte a la tabla de catálogo pg_attribute
en cambio:más limpio, más simple, más rápido. Pero no portátil a otros 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;
Produce:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle aquí
En particular, ...
- ... solo necesita proporcionar el nombre de la tabla una vez, opcionalmente calificado para el esquema.
- ... si la tabla no existe, la consulta falla inmediatamente con un útil mensaje de error.
- ... el nombre de la tabla de salida solo está calificado como esquema y entre comillas dobles donde sea necesario.
- ... esto también cubre
character(N)
(nombre internobpchar
).
Lectura adicional:
- Cómo comprobar si existe una tabla en un esquema dado
- Truncar la visualización de forma predeterminada en las declaraciones de selección psql de postgres
- PostgreSQL forzar mayúsculas para todos los datos
- Comprueba si hay cadenas vacías en las columnas de tipo de carácter