Nie pomijaj AS
słowo kluczowe dla aliasów kolumn
Nie dokładnie. Wysadza się, ponieważ pominąłeś słowo kluczowe AS
gdzie nie powinno być pominięte.
To działa:
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;
Produkuje:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Co z kolei działa zgodnie z oczekiwaniami.
podręcznik "Pomijania JAKO słowo kluczowe” :
Można pominąć słowo kluczowe AS
dla aliasów tabel, ale nie dla aliasów kolumn.
first
nie jest słowem zarezerwowanym
w Postgresie. (Kiedyś był „zarezerwowany” w starożytnym standardzie SQL-92, ale już nie w standardowym SQL.) Jest „niezarezerwowany” * być precyzyjnym. Podręcznik
:
Pomijanie AS
sprawia, że jest to właśnie taki kontekst.
quote_ident()
działa niezawodnie. Podręcznik:
format()
ze specyfikatorem %I
robi to samo.
Zarezerwowane słowa nie są wymieniane, ale są cytowane prawidłowo. Mówiąc dokładniej:wszystkie słowa kluczowe oznaczone jako „zarezerwowane” lub „(nie może być funkcją ani typem)” w kolumnie „PostgreSQL” Słowa kluczowe SQL stół .
Zgłoszę błąd w dokumentacji, aby to dodać.
Aby mieć absolutną pewność:quote_all_identifiers
Jeśli chcesz mieć absolutną pewność i nie przeszkadza ci cały dodatkowy hałas, możesz zmusić Postgresa do cytowania wszystkich identyfikatory z parametrem konfiguracyjnym quote_all_identifiers
. Podręcznik:
Obejmuje to dane wyjściowe z quote_ident()
i format()
. nie zrób to, bojąc się wszystkich dodatkowych hałasów.
Możesz ustawić parametr lokalnie za pomocą SET LOCAL
w tej samej transakcji. Na przykład:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Szybciej
To powiedziawszy, użyłbym format()
i concat()
i wybierz tabelę katalogu pg_attribute
zamiast tego:czyściej, prościej, szybciej. Ale nie można go przenieść do innych 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;
Produkuje:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle tutaj
W szczególności ...
- ... wystarczy podać nazwę tabeli tylko raz, opcjonalnie kwalifikowana według schematu.
- ... jeśli tabela nie istnieje, zapytanie natychmiast kończy się niepowodzeniem i wyświetla pomocny komunikat o błędzie.
- ... nazwa tabeli wyjściowej jest kwalifikowana tylko zgodnie ze schematem i w razie potrzeby w cudzysłowie.
- ... obejmuje to również
character(N)
(nazwa wewnętrznabpchar
).
Dalsza lektura:
- Jak sprawdzić, czy tabela istnieje w danym schemacie
- Domyślnie obcinanie wyświetlania w instrukcjach postgres psql select
- PostgreSQL wymusza wielkie litery dla wszystkich danych
- Sprawdź, czy w kolumnach znakowych występują puste ciągi