Undlad ikke AS
nøgleord for kolonnealiasser
Ikke nøjagtigt. Det sprænger, fordi du har udeladt søgeordet AS
hvor det ikke bør udelades.
Dette virker:
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;
Producerer:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Hvilket til gengæld fungerer som forventet.
manualen om "Udeladelse af AS nøgleord" :
Det er OK at udelade søgeordet AS
for tabelaliasser, men ikke for kolonnealiasser.
first
er ikke et reserveret ord
i Postgres. (Det plejede at være "reserveret" i den gamle SQL-standard SQL-92, men heller ikke længere i standard SQL.) Det er "ikke-reserveret" * for at være præcis. Manualen
:
Udeladelse af AS
gør det til netop sådan en sammenhæng.
quote_ident()
fungerer pålideligt. Manualen:
format()
med specifikationen %I
gør det samme.
Reserverede ord nævnes ikke, men citeres korrekt uanset. For at være præcis:alle nøgleord markeret med "reserveret" eller "(kan ikke være funktion eller type)" i kolonnen "PostgreSQL" i SQL-nøgleord bord .
Jeg indsender en dokumentationsfejl for at tilføje det.
For at være helt sikker:quote_all_identifiers
Hvis du vil være helt sikker og ikke har noget imod al den ekstra støj, kan du tvinge Postgres til at citere alle identifikatorer med konfigurationsparameteren quote_all_identifiers
. Manualen:
Det inkluderer output fra quote_ident()
og format()
. Jeg ville ikke gør det, frygter al den ekstra støj.
Du kan indstille parameteren lokalt med SET LOCAL
i samme transaktion. Ligesom:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Hurtigere
Når det er sagt, ville jeg bruge format()
og concat()
og målretter mod katalogtabellen pg_attribute
i stedet:renere, enklere, hurtigere. Men ikke bærbar til andre 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;
Producerer:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle her
Især ...
- ... du behøver kun at angive tabelnavnet én gang, eventuelt skema-kvalificeret.
- ... hvis tabellen ikke eksisterer, mislykkes forespørgslen med det samme med en nyttig fejlmeddelelse.
- ... outputtabelnavnet er kun skema-kvalificeret og citeret med dobbelte anførselstegn, hvor det er nødvendigt.
- ... dette dækker også
character(N)
(internt navnbpchar
).
Yderligere læsning:
- Sådan kontrollerer du, om en tabel findes i et givet skema
- Afkortning af visning som standard i postgres psql select-udsagn
- PostgreSQL force store bogstaver for alle data
- Tjek, om der er tomme strenge i tegntypekolonner