PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

quote_ident() не добавя първо кавички към името на колоната

Не пропускайте AS ключова дума за псевдоними на колони

Не точно. Издухва се, защото сте пропуснали ключовата дума AS където не трябва да се пропуска.

Това работи:

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;

Произвежда:

SELECT id, left(first, 65535) AS first from "public"."MyTableName";

Което на свой ред работи според очакванията.

ръководството за "Пропускане на AS ключова дума“ :

Добре е да пропуснете ключовата дума AS за псевдоними на таблици, но не и за псевдоними на колони.

first не е запазена дума в Postgres. (Беше „запазен“ в древния SQL стандарт SQL-92, но вече не и в стандартния SQL.) Той е „незапазен“ * за да бъдем точни. Ръководството :

Пропуска се AS го прави точно такъв контекст.

quote_ident() работи надеждно. Ръководството:

format() със спецификатора %I прави същото.

Запазените думи не се споменават, но се цитират правилно. За да бъдем точни:всички ключови думи, отбелязани с "резервирани" или "(не може да бъде функция или тип)" в колоната „PostgreSQL“ на SQL ключови думи таблица .

Ще подам документация за грешка, за да добавя това.

За да сте абсолютно сигурни:quote_all_identifiers

Ако искате да сте абсолютно сигурни и нямате нищо против целия добавен шум, можете да принудите Postgres да цитира всички идентификатори с конфигурационния параметър quote_all_identifiers . Ръководството:

Това включва изход от quote_ident() и format() . Бихнебих направете това, страхувайки се от добавения шум.

Можете да зададете параметъра локално с SET LOCAL в същата сделка. Като:

BEGIN;
SET LOCAL quote_all_identifiers = true;
SELECT ...
END;

По-бързо

Въпреки това бих използвал format() и concat() и се насочете към каталожната таблица pg_attribute вместо това:по-чисто, по-лесно, по-бързо. Но не е преносим към други 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;

Произвежда:

SELECT id, left(first, 65535) AS first FROM "MyTableName";

db<>fiddle тук

По-специално, ...

  • ... трябва да предоставите името на таблицата само веднъж, по избор квалифицирано като схема.
  • ... ако таблицата не съществува, заявката се проваля веднага с полезно съобщение за грешка.
  • ... името на изходната таблица е само квалифицирано като схема и в двойни кавички, където е необходимо.
  • ... това също обхваща character(N) (вътрешно име bpchar ).

Допълнителна информация:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. tomcat 7 JDBC пул за връзка - отделен пул за всяка база данни?

  2. Намиране на най-голямата група от последователни числа в рамките на дял

  3. Ръководство за PGpool - съвети и наблюдения:част трета

  4. SQLalchemy не извършва промени при задаване на роля

  5. SQL индексиране на varchar