Si le nombre de champs dans le CSV est constant, vous pouvez faire quelque chose comme ceci :
select a[1], a[2], a[3], a[4]
from (
select regexp_split_to_array('a,b,c,d', ',')
) as dt(a)
Par exemple :
=> select a[1], a[2], a[3], a[4] from (select regexp_split_to_array('a,b,c,d', ',')) as dt(a);
a | a | a | a
---+---+---+---
a | b | c | d
(1 row)
Si le nombre de champs dans le CSV n'est pas constant, vous pouvez obtenir le nombre maximum de champs avec quelque chose comme ceci :
select max(array_length(regexp_split_to_array(csv, ','), 1))
from your_table
et ensuite construire les a[1], a[2], ..., a[M]
pour votre requête. Donc, si la liste ci-dessus vous donne un maximum de 6, vous utiliserez ceci :
select a[1], a[2], a[3], a[4], a[5], a[6]
from (
select regexp_split_to_array(csv, ',')
from your_table
) as dt(a)
Vous pourriez combiner ces deux requêtes en une seule fonction si vous le souhaitez.
Par exemple, donnez ces données (il y a un NULL dans la dernière ligne) :
=> select * from csvs;
csv
-------------
1,2,3
1,2,3,4
1,2,3,4,5,6
(4 rows)
=> select max(array_length(regexp_split_to_array(csv, ','), 1)) from csvs;
max
-----
6
(1 row)
=> select a[1], a[2], a[3], a[4], a[5], a[6] from (select regexp_split_to_array(csv, ',') from csvs) as dt(a);
a | a | a | a | a | a
---+---+---+---+---+---
1 | 2 | 3 | | |
1 | 2 | 3 | 4 | |
1 | 2 | 3 | 4 | 5 | 6
| | | | |
(4 rows)
Puisque votre délimiteur est une simple chaîne fixe, vous pourriez également utiliser string_to_array
au lieu de regexp_split_to_array
:
select ...
from (
select string_to_array(csv, ',')
from csvs
) as dt(a);
Merci à Michael pour le rappel de cette fonction.
Vous devriez vraiment revoir le schéma de votre base de données pour éviter la colonne CSV si possible. Vous devriez plutôt utiliser une colonne de type tableau ou une table séparée.