Lassen Sie AS
nicht aus Schlüsselwort für Spaltenaliase
Nicht genau. Es explodiert, weil Sie das Schlüsselwort AS
weggelassen haben wo es nicht weggelassen werden sollte.
Das funktioniert:
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;
Erzeugt:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Was wiederum wie erwartet funktioniert.
Das Handbuch zum "Weglassen der AS Schlüsselwort" :
Das Schlüsselwort AS
kann weggelassen werden für Tabellenaliase, aber nicht für Spaltenaliase.
first
ist kein reserviertes Wort
in Postgres. (Früher war es im alten SQL-Standard SQL-92 "reserviert", aber auch nicht mehr im Standard-SQL.) Es ist "nicht reserviert" * um genau zu sein. Das Handbuch
:
Weglassen von AS
macht es zu einem solchen Kontext.
quote_ident()
funktioniert zuverlässig. Das Handbuch:
format()
mit dem Spezifizierer %I
macht dasselbe.
Reservierte Wörter werden nicht erwähnt, aber trotzdem korrekt zitiert. Genauer gesagt:alle Schlüsselwörter, die mit "reserviert" gekennzeichnet sind oder "(kann weder Funktion noch Typ sein)" in der Spalte "PostgreSQL" von dem SQL-Schlüsselwörter Tabelle .
Ich werde einen Dokumentationsfehler einreichen, um das hinzuzufügen.
Um absolut sicher zu sein:quote_all_identifiers
Wenn Sie absolut sicher sein wollen und sich nicht um all das zusätzliche Rauschen kümmern, können Sie Postgres zwingen, alle zu zitieren Identifikatoren mit dem Konfigurationsparameter quote_all_identifiers
. Das Handbuch:
Dazu gehört die Ausgabe von quote_ident()
und format()
. Ich würde nicht Tun Sie das und fürchten Sie all den zusätzlichen Lärm.
Sie können den Parameter lokal mit SET LOCAL
setzen in derselben Transaktion. Wie:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Schneller
Das heißt, ich würde format()
verwenden und concat()
und zielen Sie auf die Katalogtabelle pg_attribute
stattdessen:sauberer, einfacher, schneller. Aber nicht auf andere RDBMS portierbar:
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;
Erzeugt:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle hier
Insbesondere ...
- ... Sie müssen den Tabellennamen nur einmal angeben, optional schemaqualifiziert.
- ... falls die Tabelle nicht existiert, schlägt die Abfrage sofort mit einer hilfreichen Fehlermeldung fehl.
- ... der Name der Ausgabetabelle wird nur schemaqualifiziert und wo nötig in doppelte Anführungszeichen gesetzt.
- ... dies gilt auch für
character(N)
(interner Namebpchar
).
Weiterführende Literatur:
- Überprüfen, ob eine Tabelle in einem bestimmten Schema vorhanden ist
- Abschneiden der Anzeige standardmäßig in Postgres-Psql-Select-Anweisungen
- PostgreSQL erzwingt Großschreibung für alle Daten
- Überprüfen Sie, ob leere Zeichenfolgen in zeichenartigen Spalten vorhanden sind