151 votes

Erreur '0000-00-00 00:00:00' ne peut pas être représenté comme java.sql.Timestamp

J'ai une table de base de données contenant des dates

 (`date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'). 

J'utilise MySQL. Dans le programme, les données sont parfois transmises sans la date à la base de données. Ainsi, la valeur de la date est automatiquement assignée à 0000-00-00 00:00:00 lorsque la table data est appelée avec la colonne date, elle donne une erreur

...'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp.......

J'ai essayé de passer une valeur nulle à la date lors de l'insertion des données, mais elle est assignée à l'heure actuelle.

Y a-t-il un moyen pour que je puisse obtenir le ResultSet sans modifier la structure de la table ?

327voto

Kushan Points 2808

Vous pouvez utiliser cette URL JDBC directement dans la configuration de votre source de données :

jdbc:mysql://votre serveur:3306/votre base de données?zeroDateTimeBehavior=convertToNull

2 votes

Curieux. En lisant les autres réponses, duh, il n'y a pas de mois zéro. Qu'est-ce que cela signifie vraiment ?

3 votes

Savez-vous s'il existe un équivalent MariaDB à ajouter à mon URL jdbc ? jdbc:mariadb://localhost:3306/dev?zeroDateTimeBehavior=convertToNull ne semble pas fonctionner pour moi.

0 votes

Cela devait être CONVERT_TO_NULL pour moi.

19voto

Que la "date" "0000-00-00" soit ou non une "date" valide n'a rien à voir avec la question. "Il suffit de modifier la base de données" est rarement une solution viable.

Les faits :

  • MySQL autorise une date avec la valeur des zéros.
  • Cette "caractéristique" est largement utilisée dans d'autres langues.

Ainsi, si je "change simplement la base de données", des milliers de lignes de code PHP seront cassées.

Les programmeurs Java doivent accepter la date zéro de MySQL. y ils doivent remettre une date zéro dans la base de données, alors que d'autres langues utilisent cette "fonctionnalité".

Un programmeur se connectant à MySQL doit gérer les dates nulles et 0000-00-00 ainsi que les dates valides. Changer 0000-00-00 en null n'est pas une option viable, car alors vous ne pouvez plus déterminer si la date devait être 0000-00-00 pour la réécriture dans la base de données.

Pour 0000-00-00, je suggère de vérifier la valeur de la date sous forme de chaîne, puis de la changer en ("y",1), ou ("yyyy-MM-dd",0001-01-01), ou en toute date MySQL invalide (inférieure à l'année 1000, je crois). MySQL possède une autre "fonctionnalité" : les dates basses sont automatiquement converties en 0000-00-00.

Je me rends compte que ma suggestion est un gadget. Mais la gestion des dates par MySQL l'est aussi. Et deux maladresses ne suffisent pas. Le fait est que de nombreux programmeurs devront gérer les dates zéro de MySQL. pour toujours .

15voto

kol Points 10683

Il s'agit d'une erreur de définition de la table. Il y a es année 0, mais il n'y a pas de 0e mois et de 0e jour, le premier jour de chaque année est le 1er janvier. Donc la "date zéro" correcte est :

0000-01-01 00:00:00

(J'ai essayé cela, et ça marche).

\=== UPDATE ===

1. Temps zéro vs. JDBC

Lorsque j'ai écrit cette réponse il y a plus d'un an, je n'avais pas MySQL sous la main, j'ai donc testé uniquement la conversion des chaînes de caractères en horodatage. J'ai considéré ce test comme valide, puisque le PO s'est plaint d'une exception levée par son programme Java :

'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

J'ai donc écrit une simple application Java en console pour tester mon "temps zéro". J'ai essayé de le recréer aquí . Le code de test :

import java.sql.*;

class Main {
  public static void main (String[] args) {
    try {
      String[] s = {
        "1970-01-01 00:00:00", // UNIX epoch
        "0000-01-01 00:00:00", // My "zero time"
        "0000-00-00 00:00:00"  // The OP's zero time
      };
      for (int i = 0; i < s.length; ++i) {
        Timestamp t = Timestamp.valueOf(s[i]);
        System.out.println(t.toString() + ", " + t.getTime());
      }
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
  }
}

Le résultat :

1970-01-01 00:00:00.0, 0
0001-01-01 00:00:00.0, -62167392000000
Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]

Il est intéressant de noter que, bien que ma chaîne de temps zéro puisse être convertie en java.sql.Timestamp sa version en chaîne est erronée. L'exception levée pour l'heure zéro du PO est également étrange, car il n'y a aucun problème avec son format.

2. Temps zéro contre MySQL

J'ai créé aujourd'hui un simple bidule MySQL pour tester les timestamps par défaut, voir aquí . Définition du tableau :

CREATE TABLE test 
(
  id INT AUTO_INCREMENT PRIMARY KEY, 
  t TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:01',
  x DOUBLE NOT NULL
);

Données d'essai :

INSERT INTO test (x) VALUES (3.14);
INSERT INTO test (t, x) VALUES ('2013-08-27 11:36:33', 42);

Contenu de la table :

ID    T                                 X
1     January, 01 1970 00:00:01+0000    3.14
2     August, 27 2013 11:36:33+0000     42

J'ai expérimenté avec différents timestamps par défaut, et j'ai trouvé que le défaut ci-dessus est la valeur minimale acceptée par MySQL. Par exemple, tous ces timestamps sont invalides : '1970-01-01 00:00:00' , '0000-01-01 00:00:00' , '0000-00-00 00:00:00' . Le message d'erreur est le suivant Invalid default value o Cannot convert value to TIMESTAMP en fonction de sql_mode . L'explication se trouve dans le doc :

Le type de données TIMESTAMP est utilisé pour les valeurs qui contiennent à la fois une date et une heure. et de l'heure. TIMESTAMP est compris entre '1970-01-01 00:00:01' UTC et 2038-01-19 03:14:07' UTC.

En conclusion Il s'est avéré que la conversion des chaînes en horodatage de MySQL est plus stricte que celle de l'API JDBC. En d'autres termes, le temps zéro que j'ai suggéré dans ma réponse initiale ne fonctionne pas avec MySQL.

9voto

Ajoutez l'instruction suivante au protocole JDBC-mysql :

?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8

par exemple :

jdbc:mysql://localhost/infra?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8

5 votes

Soyez prudent avec cette approche. Elle fonctionne comme un charme, mais elle a mis hors service un serveur de production (elle fonctionnait parfaitement en mode développement...). Ce que nous avons appris, c'est que vous devez citer la chaîne de caractères car le & est interprété comme un caractère spécial dans certains contextes, ce qui donne à la ligne une signification complètement différente...

6voto

npe Points 6521

Au lieu d'utiliser des faux rendez-vous comme 0000-00-00 00:00:00 o 0001-01-01 00:00:00 (cette dernière devrait être acceptée car il s'agit d'une date valide), modifiez le schéma de votre base de données, pour permettre à NULL valeurs.

ALTER TABLE table_name MODIFY COLUMN date TIMESTAMP NULL

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X