PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

quote_ident() tidak menambahkan tanda kutip ke nama kolom terlebih dahulu

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 internal bpchar ).

Bacaan lebih lanjut:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. pilih/tampilkan id serial yang terakhir dimasukkan di postgres

  2. KESALAHAN:pengenal batas nol-panjang pada atau di dekat LINE 1:DELETE FROM region WHERE region. =$1

  3. Keuntungan menggunakan URLField dibandingkan TextField?

  4. PostgreSQL menggunakan pg_trgm lebih lambat dari pemindaian penuh

  5. Bagaimana cara mengonversi bilangan bulat menjadi string sebagai bagian dari kueri PostgreSQL?