Re: Longueur des colonnes char dans une view

From: Ludovic Levesque <luddic(at)gmail(dot)com>
To: c(dot)maumont(at)univitis(dot)fr
Cc: pgsql-fr-generale(at)postgresql(dot)org
Subject: Re: Longueur des colonnes char dans une view
Date: 2010-01-14 09:37:07
Message-ID: 162718d41001140137h33208bcenad545d093d02557a@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-fr-generale

Bonjour,

je n'ai pas pu tester sur une 8.1, mais sur une 8.3.

Peut-être en forçant un SELECT au dessus de l'UNION, voir tuv2:

CREATE TABLE t(c50 character(50));

CREATE OR REPLACE VIEW tuv1 AS
SELECT 'R'::character(1) AS t_vw_essai, t.c50::character(1) as f1,
t.c50::character(50) as f50
FROM t
UNION
SELECT 'R'::character(1) AS t_vw_essai, t.c50::character(1) as f1,
t.c50::character(50) as f50
FROM t;

CREATE OR REPLACE VIEW tuv2 AS
SELECT t_vw_essai::character(1), f1::character(1), f50::character(50)
FROM (
SELECT 'R'::character(1) AS t_vw_essai, t.c50::character(1) as
f1, t.c50::character(50) as f50
FROM t
UNION
SELECT 'R'::character(1) AS t_vw_essai, t.c50::character(1) as
f1, t.c50::character(50) as f50
FROM t
) as tmp
;

select table_name, column_name, character_maximum_length from
information_schema.columns where table_name IN ('t', 'tuv1', 'tuv2');
table_name | column_name | character_maximum_length
------------+-------------+--------------------------
t | c50 | 50
tuv1 | t_vw_essai | 1
tuv1 | f1 | 1
tuv1 | f50 | 50
tuv2 | t_vw_essai | 1
tuv2 | f1 | 1
tuv2 | f50 | 50
(7 rows)

Ludo

2010/1/14 <c(dot)maumont(at)univitis(dot)fr>:
>> >>>
>> >>> Bonjour,
>> >>>
>> >>> Quand je crée une view, les colonnes en integer ou numeric sont
>> bien
>> >>> caractérisée dans information_schema.columns en terme de précision.
>> >>>
>> >>> Par contre, les colonnes en char(x) dans les tables d'origine
>> >>> apparaissent avec character_maximum_length non renseigné.
>> >>>
>> >>> Est-il possible de fixer cette longueur ?
>> >>>
>> >>> Actuellement je crée ma view avec :
>> >>>
>> >>> CREATE OR REPLACE VIEW vw_essai
>> >>> (
>> >>>   t_vw_essai,
>> >>>   n_ent_cmd,
>> >>>   soc,
>> >>>   ref_cli,
>> >>>   mt_ht
>> >>> )
>> >>> as
>> >>> select 'R'::char(1),n_ent_cmd,soc,ref_cli,mt_ht from ent_res
>> >>> union
>> >>> select 'M'::char(1),n_ent_cmd,soc,ref_cli,mt_ht from ent_mch;
>> >>>
>> >>> n_ent_cmd est un integer, soc un char(1), ref_cli un char(50) et
>> >> mt_ht
>> >>> un numeric(12,2).
>> >>>
>> >>> Postgresql 8.1 sur DEBIAN/ETCH
>> >>>
>> >> J'ai peut-être mal compris ta question, en tout cas je n'arrives pas
>> à
>> >> reproduire ton problème avec un serveur PG 8.2.x :
>> >>
>> >> create table txt_7 (n_ent_cmd integer,soc char(1),ref_cli char(50));
>> >>
>> >> create view v_txt7 (t_vw_essai,n_ent_cmd,soc,ref_cli)
>> >> as select 'R'::char(1),n_ent_cmd,soc,ref_cli from txt_7;
>> >>
>> >> select table_name, column_name, character_maximum_length
>> >> from information_schema.columns
>> >> where column_name IN ('soc','ref_cli');
>> >>
>> >>  table_name | column_name | character_maximum_length
>> >> ------------+-------------+--------------------------
>> >>  txt_7      | soc         |                        1
>> >>  txt_7      | ref_cli     |                       50
>> >>  v_txt7     | soc         |                        1
>> >>  v_txt7     | ref_cli     |                       50
>> >>
>> >> Est-ce bien c'est le résultat que tu attends ?
>> >>
>> >> --
>> >> damien
>> >
>> > C'est exactement ce que je voudrais, mais j'obtiens la colonne
>> character_maximum_length à null.
>> > Si je ne mets pas d'union dans la vue, j'obtiens la même chose que
>> toi (merci damien, tu as fais avancer mon schmilblick),
>> > ma 8.1 fonctionne donc comme ta 8.2 sur ce point, c'est déjà ça.
>> > Le problème viendrais donc de l'union, il semble que postgresql ne
>> sache pas quelle longueur prendre pour les char(x) dans ce cas.
>> >
>> > La question est donc de savoir si le problème est propre à ma version
>> et si il y a une syntaxe particulière du CREATE VIEW permettant de
>> forcer ces longueurs.
>> >
>>
>> Pas mieux,
>>
>> create table txt_8 (n_ent_cmd integer,soc char(1),ref_cli char(50));
>>
>> create view v_txt8 (t_vw_essai,n_ent_cmd,soc,ref_cli)
>> as select 'R'::char(1),n_ent_cmd,soc,ref_cli from txt_7
>> union select 'M'::char(1),n_ent_cmd,soc,ref_cli from txt_8;
>>
>> select table_name, column_name, character_maximum_length
>> from information_schema.columns where column_name IN ('soc','ref_cli');
>>
>>  table_name | column_name | character_maximum_length
>> ------------+-------------+--------------------------
>>  txt_7      | soc         |                        1
>>  txt_7      | ref_cli     |                       50
>>  v_txt7     | soc         |                        1
>>  v_txt7     | ref_cli     |                       50
>>  txt_8      | soc         |                        1
>>  txt_8      | ref_cli     |                       50
>>  v_txt8     | soc         |                        1
>>  v_txt8     | ref_cli     |                       50
>>
>>
>> Par contre, si les deux tables n'ont pas le même schéma. Exemple :
>>
>> create table txt_9 (n_ent_cmd integer,soc char(10),ref_cli varchar);
>>
>> create view v_txt9 (t_vw_essai,n_ent_cmd,soc,ref_cli)
>> as select 'R'::char(1),n_ent_cmd,soc,ref_cli from txt_9
>> union select 'M'::char(1),n_ent_cmd,soc,ref_cli from txt_8;
>>
>> select table_name, column_name, character_maximum_length
>> from information_schema.columns where column_name IN ('soc','ref_cli');
>>
>>  table_name | column_name | character_maximum_length
>> ------------+-------------+--------------------------
>>  txt_7      | soc         |                        1
>>  txt_7      | ref_cli     |                       50
>>  v_txt7     | soc         |                        1
>>  v_txt7     | ref_cli     |                       50
>>  txt_8      | soc         |                        1
>>  txt_8      | ref_cli     |                       50
>>  v_txt8     | soc         |                        1
>>  v_txt8     | ref_cli     |                       50
>>  txt_9      | soc         |                       10
>>  txt_9      | ref_cli     |
>>  v_txt9     | soc         |
>>  v_txt9     | ref_cli     |
>>
>> A priori les colonnes CHAR de tes tables ent_res et ent_mch n'ont pas
>> la
>> même longuer... Du coup j'imagine que PostgreSQL converti à la volée le
>> type des colonnes en VARCHAR.
>>
>> Si les colonnes que tu veux unir ne sont pas homogènes, tu peux
>> simplement "forcer" leur taille avec un cast explicite. Par exemple
>> pour
>> la colonne soc:
>>
>> CREATE OR REPLACE VIEW vw_essai (...) as
>> select 'R'::char(1),n_ent_cmd,soc::char(42),ref_cli,mt_ht from ent_res
>> union
>> select 'M'::char(1),n_ent_cmd,soc::char(42),ref_cli,mt_ht from ent_mch;
>
> J'essaye donc :
>
> CREATE OR REPLACE VIEW vw_essai AS
>  SELECT 'R'::character(1) AS t_vw_essai, ent_res.soc::character(1), ent_res.ref_cli::character(50)
>   FROM ent_res
> UNION
>   SELECT 'R'::character(1) AS t_vw_essai, ent_res.soc::character(1), ent_res.ref_cli::character(50)
>   FROM ent_res;
>
> select table_name, column_name, character_maximum_length from information_schema.columns where table_name IN ('ent_res','vw_essai') and column_name IN ('t_vw_essai','soc','ref_cli');
>
> et j'obtiens :
>
> table_name | column_name | character_maximum_length
> ------------+-------------+--------------------------
>  ent_res    | soc         |                        1
>  ent_res    | ref_cli     |                       50
>  vw_essai   | t_vw_essai  |
>  vw_essai   | soc         |
>  vw_essai   | ref_cli     |
>
> Même en faisant l'union sur la même table (les colonnes ont donc la même longueur) et en forçant le cast, ça ne marche pas.
> On dirait un bug, est-il propre à la 8.1 ?
> Je suis près à passer à une version supérieure (8.4) mais seulement si ça corrige le problème,
> sinon ma 8.1 me convient parfaitement.
>
> Y-a-t-il une syntaxe qui permettrait de caster les colonnes de la view (je n'ai rien trouvé dans la doc), un truc du genre :
>
> CREATE OR REPLACE VIEW vw_essai
> (
> t_vw_essai char(1),
> soc char(1),
> ref_cli char(50)
> )
>
>  AS
>  SELECT 'R'::character(1) AS t_vw_essai, ent_res.soc::character(1), ent_res.ref_cli::character(50)
>   FROM ent_res
> UNION
>   SELECT 'R'::character(1) AS t_vw_essai, ent_res.soc::character(1), ent_res.ref_cli::character(50)
>   FROM ent_res;
>
> Merci pour l'aide.
>
>
>
>
>
>
>
> --
> Sent via pgsql-fr-generale mailing list (pgsql-fr-generale(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-fr-generale
>

In response to

Responses

Browse pgsql-fr-generale by date

  From Date Subject
Next Message damien clochard 2010-01-14 09:45:16 Re: Longueur des colonnes char dans une view
Previous Message c.maumont 2010-01-14 08:58:34 Re: Longueur des colonnes char dans une view