D'où vient la colonne magique «nom»?


11

Je l'ai eu par accident:

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)

La deuxième requête renvoie un tuple contenant une ligne entière. Utilisation de postgres 9.0.1.

Edit: la définition du site sur demande. Je n'ai pas vraiment d'importance, cette bizarrerie fonctionne pour n'importe quelle table.

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

Il serait utile de montrer la définition de site.
Peter Eisentraut

~ Il ne importe parce que maintenant nous pouvons voir qu'il n'y a pas de « nom » dans sitepour commencer. Pourquoi voudriez-vous rechercher une colonne qui n'existe pas?
jcolebrand

1
Essayez select site from site- cela vous aidera à comprendre la réponse de Gaius plus en détail
Jack dit essayez topanswers.xyz

Réponses:


11

NAMEest en fait une fonction . C'est une bizarrerie de Postgres qu'une fonction avec un seul argument, par exemple, function(arg)peut également être appelée as arg.function. De la documentation:

L'équivalence entre notation fonctionnelle et notation attributaire permet d'utiliser des fonctions sur des types composites pour émuler des "champs calculés".

NAMEest un type interne pour les noms d'objets , et cette fonction convertit son argument en ce type et le renvoie.


Merci, je ne le savais pas. Qu'est-ce qui me dérange si cette fonction particulière "nom" est documentée quelque part?
hegemon

Mis à jour ma réponse
Gaius

2
Plus précisément, le rowtype est converti en textcar il s'agit du type d'entrée de la fonction name. La namefonction convertit alors (pas la conversion) la chaîne d'entrée en type name(ce qui aura également pour effet secondaire de tronquer à 64 octets)
Jack dit: essayez topanswers.xyz

3

Notez également que la conversion implicite en nom a été supprimée dans PostgreSQL 8.3, ce qui signifie que ce comportement ne fonctionne plus. Il est pratiquement impossible d'obtenir accidentellement ce comportement dans PostgreSQL 8.3 et versions ultérieures car les tuples ne se convertissent pas automatiquement en texte.

Donc en 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;

mais pour obtenir ce comportement, nous devons:

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

Ou nous pourrions définir notre propre fonction de nom en prenant le type comp_table_test et en retournant ce que nous voudrions.


Je ne comprends pas cette réponse. Vous dites que la question posée ci-dessus ne devrait plus être un problème sur 8.3 ou supérieur? Pourtant, la question porte sur 9.0
Colin 't Hart

0

"nom" est un mot clé réservé . Vous devez donc "citer" le mot-clé pour l'utiliser:

SELECT "name" FROM site;

Cela a résolu certains de ces problèmes pour moi dans le passé, même si le code que vous avez publié devrait également fonctionner sans devis. D'autre part

select site.name from site;

mot parce que vous utilisez explicitement le schéma pour résoudre le nom de la colonne


1
Beaucoup de mots réservés peuvent être utilisés, et dans ce cas, la citation n'aide pas. En effet, si site.name n'existe pas en tant que colonne, avant la version 8.3, ce qui se passerait, c'est que vous commenceriez à rechercher des fonctions de nom prenant un type de données de site ou un type implicitement casté à partir du site. Étant donné que le site pourrait être implicitement converti en texte, le nom (texte) serait utilisé. Par conséquent, select site.name from sitepourrait être implicitement transformé à select name(site::text) from sitequi vient la magie.
Chris Travers
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.