Jangan hilangkan AS
kata kunci untuk alias kolom
Tidak persis. Ini meledak karena Anda menghilangkan kata kunci AS
di mana itu tidak boleh dihilangkan.
Ini berfungsi:
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;
Menghasilkan:
SELECT id, left(first, 65535) AS first from "public"."MyTableName";
Yang berfungsi seperti yang diharapkan pada gilirannya.
manual tentang "Menghilangkan SEBAGAI Kata Kunci" :
Tidak apa-apa untuk menghilangkan kata kunci AS
untuk alias tabel, tetapi tidak untuk alias kolom.
first
bukan kata yang dicadangkan
di Postgres. (Dulu "reserved" dalam standar SQL kuno SQL-92, tetapi tidak lagi dalam SQL standar.) Ini "non-reserved" * lebih tepatnya. Manual
:
Menghilangkan AS
membuatnya menjadi konteks seperti itu.
quote_ident()
bekerja dengan andal. Manual:
format()
dengan penentu %I
melakukan hal yang sama.
Kata-kata yang dicadangkan tidak disebutkan, tetapi dikutip dengan benar terlepas dari itu. Tepatnya:semua kata kunci bertanda "reserved" atau "(tidak dapat berupa fungsi atau tipe)" di kolom "PostgreSQL" dari Kata Kunci SQL meja .
Saya akan mengajukan bug dokumentasi untuk menambahkannya.
Untuk benar-benar yakin:quote_all_identifiers
Jika Anda ingin benar-benar yakin dan tidak keberatan dengan semua kebisingan tambahan, Anda dapat memaksa Postgres untuk mengutip semua pengenal dengan parameter konfigurasi quote_all_identifiers
. Manual:
Itu termasuk output dari quote_ident()
dan format()
. Saya akan tidak lakukan itu, takut akan semua kebisingan tambahan.
Anda dapat menyetel parameter secara lokal dengan SET LOCAL
dalam transaksi yang sama. Seperti:
BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;
Lebih cepat
Yang mengatakan, saya akan menggunakan format()
dan concat()
dan targetkan tabel katalog pg_attribute
sebagai gantinya:lebih bersih, lebih sederhana, lebih cepat. Tetapi tidak portabel untuk RDBMS lain:
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;
Menghasilkan:
SELECT id, left(first, 65535) AS first FROM "MyTableName";
db<>fiddle di sini
Khususnya, ...
- ... Anda hanya perlu memberikan nama tabel satu kali, secara opsional memenuhi syarat skema.
- ... jika tabel tidak ada, kueri akan langsung gagal dengan pesan kesalahan yang berguna.
- ... nama tabel keluaran hanya memenuhi syarat skema dan dikutip ganda jika perlu.
- ... ini juga mencakup
character(N)
(nama internalbpchar
).
Bacaan lebih lanjut:
- Cara memeriksa apakah ada tabel dalam skema tertentu
- Memotong tampilan secara default dalam pernyataan pilih psql postgres
- PostgreSQL memaksa huruf besar untuk semua data
- Periksa apakah ada string kosong di kolom tipe karakter