Question

J'ai une requête volumineuse dans une base de données PostgreSQL. La requête ressemble à ceci:

SELECT * FROM table1, table2, ... WHERE table1.id = table2.id...

Lorsque j'exécute cette requête en tant que requête SQL, elle renvoie la ligne souhaitée.

Mais lorsque j'essaie d'utiliser la même requête pour créer une vue, une erreur est renvoyée:

" erreur: colonne " id " spécifié plus d'une fois. "

(J'utilise pgAdminIII lors de l'exécution des requêtes.)

Je suppose que cela se produit car le jeu de résultats aura plusieurs colonnes nommées "id". Peut-on résoudre ce problème sans écrire tous les noms de colonne dans la requête?

Était-ce utile?

La solution

Cela se produit car une vue aurait deux colonnes id nommées, l'une de table1 et l'autre de table2, en raison de la sélection *.

Vous devez spécifier quel identifiant vous souhaitez dans la vue.

SELECT table1.id, column2, column3, ... FROM table1, table2 
WHERE table1.id = table2.id

La requête fonctionne car elle peut avoir des colonnes portant le même nom ...

postgres=# select 1 as a, 2 as a;
 a | a
---+---
 1 | 2
(1 row)

postgres=# create view foobar as select 1 as a, 2 as a;
ERROR:  column "a" duplicated
postgres=# create view foobar as select 1 as a, 2 as b;
CREATE VIEW

Autres conseils

Si seules les colonnes de jointure sont dupliquées (c'est-à-dire qu'elles portent les mêmes noms), vous pouvez vous en tirer en changeant:

select *
from a, b
where a.id = b.id

à:

select *
from a join b using (id)

Si vous êtes arrivé ici parce que vous essayez d'utiliser une fonction telle que to_date et que vous obtenez le " défini plusieurs fois " erreur, notez que vous devez utiliser un alias de colonne pour les fonctions, par exemple:

to_date(o.publication_date, 'DD/MM/YYYY') AS publication_date

Pas de méthode intégrée dans le langage pour le résoudre (et franchement, * est une mauvaise pratique en général car il peut provoquer des défauts cachés lorsque les schémas de table changent - vous pouvez faire table1. *, table2.acolumn, tabl2.bcolumn si vous voulez utiliser toutes les tables d’une manière sélective), mais si PostgreSQL supporte INFORMATION_SCHEMA, vous pouvez faire quelque chose comme:

DECLARE @sql AS varchar

SELECT @sql = COALESCE(@sql + ', ', '') 
    + '[' + TABLE_NAME + '].[' + COLUMN_NAME + ']'
    + CHAR(13) + CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME IN ('table1', 'table2')
ORDER BY TABLE_NAME, ORDINAL_POSITION

PRINT @sql

Et collez les résultats pour économiser beaucoup de frappe. Vous devrez bien sûr aliaser manuellement les colonnes qui portent le même nom. Vous pouvez également coder des noms uniques (si ce n’est pas mon cas):

SELECT @sql = COALESCE(@sql + ', ', '') 
    + '[' + TABLE_NAME + '].[' + COLUMN_NAME + '] '
    + 'AS [' + TABLE_NAME + '_' + COLUMN_NAME + ']'
    + CHAR(13) + CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME IN ('table1', 'table2')
ORDER BY TABLE_NAME, ORDINAL_POSITION
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top