Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Venant juste de passer de la 8.4 à la 9.0, je viens de rencontrer un petit soucis. Une fonction en Plpgsql doit retourner un type de données propriétaire. Ce type comporte un varchar(n). Dans la fonction , le retour se fait, après concaténation de chaînes, par un cast varchar. Voici les déclarations :
CREATE TYPE my_type AS (a int2,b varchar(61), c int2);
CREATE OR REPLACE FUNCTION my_fonction(integer, integer, integer,boolean) RETURNS SETOF my_type AS '
.
.
.
for my_record in select ...., (ch1 ||'' ''||ch2)::varchar ....
Et voici le message d'erreur obtenu avec cette nouvelle version :
Returned type character varying does not match expected type character varying(61) in column 2
Si je remplace par (ch1 ||'' ''||ch2)::varchar(61) cela fonctionne. Mais là n'est pas le but car il faudrait vérifier l'ensemble des fonctions et programmes. Je ne comprends pas le pourquoi, surtout que cette erreur n'est présente qu'en 9.0 et que cette syntaxe me semble correcte.
Merci si vous avez une idée sur la question.
Hors ligne
Un cast vers varchar() et un cast vers varchar(61) ne sont pas du tout identiques. Dans le premier cas, je peux avoir autant de caractères que je le souhaite alors que dans le second, je suis limité à 61. Le message d'erreur est donc logique. La différence entre les versions est certainement dû au travail effectué pour améliorer une vérification stricte des types.
Guillaume.
Hors ligne
Pourtant il me semble bien que la norme SQL prévoies le troncage. Il s'agit, tout de même, du même type fondamental. Alors pourquoi en ligne de commande, un select ('test'::varchar)::varchar(3); passe correctement en renvoyant 'tes' ? Est-ce à cause du traitement de la fonction que la logique diffère ?
Hors ligne
SQL prévoit le contrôle. Il n'y a que MySQL qui tronque des données sans vous le dire. Les autres refusent d'intégrer la donnée. Il s'agit de l'intégrité de vos données, et peu de SGBD le prennent à la légère. Vous lui annoncez qu'une chaîne ne doit pas dépasser 61 caractères, il vous prévient si vous essayez de violer cette contrainte.
Marc.
Hors ligne
Et pour répondre à la question "pourquoi en ligne de commande, un select ('test'::varchar)::varchar(3); passe correctement en renvoyant 'tes' ?", tout simplement parce que vous forcez la conversion, contrairement au premier cas.
Guillaume.
Hors ligne
Merci à vous pour ces promptes précisions.
Juste un petit clin d'oeil à la documentation sur les varchar(n) :
An attempt to store a longer string into a column of these types will result in an error, unless the excess characters are all spaces, in which case the string will be truncated to the maximum length
Pas si clean que cela
Hors ligne
Pas si clean que cela
PostgreSQL ne peut rien y faire. Cette étrangeté est requise par la norme SQL.
Guillaume.
Hors ligne
Oui, les caractères blanc et les chaînes vides ont souvent des traitements un peu étranges. Et ce n'est pas le cas que pour la norme SQL…
Je présume que c'est là pour faciliter la compatibilité avec les vieux système (en Cobol par exemple) qui avaient des enregistrements de taille fixe et faisaient du padding avec des blancs. Mais c'est vrai que c'est une des saletés de la norme SQL.
Marc.
Hors ligne
Pages : 1