PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Générer une erreur lorsque la date n'est pas valide

Vous pouvez écrire votre propre fonction to_date(), mais vous devez l'appeler avec son nom qualifié par le schéma. (J'ai utilisé le schéma "public", mais il n'y a rien de spécial à ce sujet.)

create or replace function public.to_date(any_date text, format_string text)
returns date as
$$
select to_date((any_date::date)::text, format_string);
$$
language sql

L'utilisation du nom de la fonction nue exécute la fonction native to_date().

select to_date('20130229', 'yyyymmdd');
2013-03-01

L'utilisation du nom qualifié par le schéma exécute la fonction définie par l'utilisateur.

select public.to_date('20130229', 'yyyymmdd');
ERROR: date/time field value out of range: "20130229"
SQL state: 22008

Je sais que ce n'est pas tout à fait ce que vous cherchez. Mais . . .

  • C'est plus simple que de reconstruire PostgreSQL à partir des sources.
  • La correction de votre code source SQL et PLPGSQL existant est une simple recherche et remplacement avec un éditeur de streaming. Je suis à peu près sûr que cela ne peut pas mal tourner, tant que vous voulez vraiment chaque utilisation du to_date() natif devient public.to_date().
  • La fonction native to_date() fonctionnera toujours comme prévu. Les extensions et autres codes peuvent s'appuyer sur son comportement quelque peu particulier. Réfléchissez bien et longtemps avant de modifier le comportement des fonctions natives.

Les nouveaux SQL et PLPGSQL devraient cependant être revus. Je ne m'attendrais pas à ce que les développeurs se souviennent d'écrire public.to_date() à chaque fois. Si vous utilisez le contrôle de version, vous pourrez peut-être écrire un hook de précommit pour vous assurer que seul public.to_date() est utilisé.

La fonction native to_date() a un comportement que je ne vois pas documenté. Non seulement vous pouvez l'appeler avec le 29 février, mais vous pouvez l'appeler avec le 345 février ou le 9999 février.

select to_date('201302345', 'yyyymmdd');
2014-01-11

select to_date('2013029999', 'yyyymmdd');
2040-06-17