Sla AS
niet weg sleutelwoord voor kolomaliassen
Niet precies. Het ontploft omdat je het zoekwoord AS
. hebt weggelaten waar het niet mag worden weggelaten.
Dit werkt:
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;
Produceert:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Wat op zijn beurt weer werkt zoals verwacht.
De handleiding over "Het weglaten van de ALS Sleutelwoord" :
Het is oké om het trefwoord AS
weg te laten voor tabelaliassen, maar niet voor kolomaliassen.
first
is geen gereserveerd woord
in Postgres. (Het was "gereserveerd" in de oude SQL-standaard SQL-92, maar ook niet meer in standaard SQL.) Het is "niet-gereserveerd" * precies zijn. De handleiding
:
Weglaten van AS
maakt het zo'n context.
quote_ident()
werkt betrouwbaar. De handleiding:
format()
met de specificatie %I
doet hetzelfde.
Gereserveerde woorden worden niet genoemd, maar toch correct geciteerd. Om precies te zijn:alle trefwoorden gemarkeerd met "gereserveerd" of "(kan geen functie of type zijn)" in de kolom "PostgreSQL" van de SQL-sleutelwoorden tafel .
Ik zal een documentatiebug indienen om dat toe te voegen.
Om absoluut zeker te zijn:quote_all_identifiers
Als je absoluut zeker wilt zijn en alle toegevoegde ruis niet erg vindt, kun je Postgres dwingen om alles te citeren identifiers met de configuratieparameter quote_all_identifiers
. De handleiding:
Dat omvat uitvoer van quote_ident()
en format()
. Ik zou niet doe dat, bang voor al het extra lawaai.
U kunt de parameter lokaal instellen met SET LOCAL
in dezelfde transactie. Vind ik leuk:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Sneller
Dat gezegd hebbende, zou ik format()
. gebruiken en concat()
en target de catalogustabel pg_attribute
in plaats daarvan:schoner, eenvoudiger, sneller. Maar niet overdraagbaar naar andere 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;
Produceert:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle hier
Met name, ...
- ... u hoeft de tabelnaam maar één keer op te geven, eventueel schema-gekwalificeerd.
- ... als de tabel niet bestaat, mislukt de query onmiddellijk met een handige foutmelding.
- ... de naam van de uitvoertabel is alleen schema-gekwalificeerd en dubbel geciteerd waar nodig.
- ... dit omvat ook
character(N)
(interne naambpchar
).
Verder lezen:
- Hoe te controleren of een tabel in een bepaald schema bestaat
- Standaard weergave inkorten in postgres psql select-instructies
- PostgreSQL forceert hoofdletters voor alle gegevens
- Controleer of er lege tekenreeksen aanwezig zijn in kolommen van het tekentype