Звідки береться чарівний стовпчик "ім'я"?


11

Я отримав це випадково:

db=> select name from site;
ERROR:  column "name" does not exist
LINE 1: select name from site;
               ^
db=> select site.name from site;
     name
---------------
 (1,mysitename)
(1 row)

Другий запит повертає кортеж, що містить цілий ряд. Використання постгресів 9.0.1.

Редагувати: визначення сайту за запитом. Я не дуже важливий, ця химерність працює для будь-якої таблиці.

db=> \d site
                         Table "public.site"
 Column |  Type   |                     Modifiers
--------+---------+---------------------------------------------------
 id     | integer | not null default nextval('site_id_seq'::regclass)
 title  | text    | not null

Це допомогло б показати визначення site.
Пітер Ейзентрав

~ Це має значення, тому що зараз ми можемо побачити, що siteдля початку немає "імені" . Навіщо ви запитуєте стовпець, який не існує?
jcolebrand

1
Спробуйте select site from site- це допоможе зрозуміти відповідь Гая детальніше
Джек каже спробувати topanswers.xyz

Відповіді:


11

NAMEнасправді є функцією . Це химерність Postgres, що функцію з одним аргументом, наприклад, function(arg)можна також викликати як arg.function. З документів:

Еквівалентність між функціональними позначеннями і позначеннями атрибутів дає можливість використовувати функції на складених типах для емуляції "обчислених полів".

NAMEє внутрішнім типом імен об'єктів , і ця функція передає свій аргумент цьому типу і повертає його.


Спасибі, я цього не знав. Що мене турбує, якщо саме ця функція "ім'я" зафіксована десь?
гегемон

Оновлено мою відповідь
Гай

2
Точніше, rowтип передається textтому, що це вхідний тип функції name. Потім nameфункція перетворює (не вкладає) вхідний рядок у тип name(що також матиме побічний ефект обрізання до 64 байт)
Джек каже спробувати topanswers.xyz

3

Також зауважте, що неявна передача на ім’я була видалена в PostgreSQL 8.3, що означає, що така поведінка більше не працює. Практично неможливо випадково отримати таку поведінку в PostgreSQL 8.3 і вище, оскільки кортежі не перетворюються автоматично в текст.

Так у 9.1:

or_examples=# select c.name from comp_table_test c;
ERROR:  column c.name does not exist
LINE 1: select c.name from comp_table_test c;

але щоб отримати таку поведінку, ми повинні:

or_examples=# select name(c::text) from comp_table_test c;

Або ми могли б визначити власну функцію імені, приймаючи тип comp_table_test і повертаючи все, що б нам хотілося.


Я не розумію цієї відповіді. Ви говорите, що поставлене вище питання не повинно бути проблемою на 8.3 чи вище? І все-таки питання задається про 9.0
Colin 't Hart

0

"ім'я" - це зарезервоване ключове слово . Тому вам слід "цитувати" ключове слово, щоб використовувати його:

SELECT "name" FROM site;

Це вирішило деякі з цих проблем для мене в минулому, хоча код, який ви опублікували, також повинен працювати без цитування. З іншої сторони

select site.name from site;

слово, оскільки ви явно використовуєте схему для вирішення назви стовпця


1
Можна використовувати багато зарезервованих слів, і в цьому випадку цитування не допомагає. Це тому, що якщо site.name не існує як стовпчик, то до 8.3, що трапиться, ви б почали шукати функції імен, приймаючи тип даних про сайт або тип, який неявно передається з сайту. Оскільки сайт може бути неявним для тексту, ім'я (текст) буде використано. Отже, це select site.name from siteможе бути неявно перетворене select name(site::text) from site, звідки походить магія.
Кріс Траверс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.