English


English


Knowledge base

Handle "DATE" datatypes with MySQL and MariaDB


KB-LJW-DB-104



  




Related articles and resources




Dates and MySQL: a failed marriage




The moment of explosion


Thank MySQL




Tips and best practices


Tips when designing the schema


Store dates in DATETIME


Do not store dates in VARCHAR

SQL
-- Read from the "d_date_txt" field of type VARCHAR.
-- Attempt to convert the string to a date according to the specified pattern:
----- Will fail on the first piece of data that does not match the pattern!
SELECT
   STR_TO_DATE(d_date_txt, '%Y-%m-%d %H:%i:%s') AS d_date_safe
FROM myTable;


Define a default value


NULL
SQL
-- Table creation
-- Use a NULL value by default => Valid with MySQL and MariaDB
CREATE TABLE contactRequests (
  d_dateReceived DATETIME NULL DEFAULT NULL
);


CURRENT_TIMESTAMP
SQL
-- Table creation
CREATE TABLE contactRequests (
   d_dateReceived DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Alter an existing table
ALTER TABLE contactRequests MODIFY d_dateReceived DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;


SQL
-- Do not specify the "d_dateReceived" field:
-- it is automatically populated with the current date.
INSERT INTO contactRequests (s_firstname, s_lastname)
VALUES ('John', 'Duff');

-- Explicitly provide CURRENT_TIMESTAMP
-- (redundant and unnecessary, but functional)
INSERT INTO contactRequests (s_firstname, s_lastname, d_dateReceived)
VALUES ('John', 'Duff', CURRENT_TIMESTAMP);

-- Explicitly provide NULL
-- => CAUSES AN ERROR!
INSERT INTO contactRequests (s_firstname, s_lastname, d_dateReceived)
VALUES ('John', 'Duff', NULL);


0000-00-00 00:00:00
SQL
-- Table creation
-- Using an invalid date by default => historically tolerated by MySQL
CREATE TABLE contactRequests (
   d_dateReceived DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'
);



Make the date mandatory

SQL
-- Create the table
---- d_dateReceived is mandatory
---- NULL is forbidden
---- no default value is defined
---- Any INSERT/UPDATE query must explicitly provide d_dateReceived, otherwise it fails.
CREATE TABLE contactRequests (
  d_dateReceived DATETIME NOT NULL
);

-- Alter the existing table
-- Will fail if even one row still contains NULL in d_dateReceived => Clean the table first.
---- d_dateReceived is mandatory
---- NULL is forbidden
---- no default value is defined
---- Any INSERT/UPDATE query must explicitly provide d_dateReceived, otherwise it fails.
ALTER TABLE contactRequests
MODIFY d_dateReceived DATETIME NOT NULL;



SQL
-- Example with no value provided:
-- The query fails.
INSERT INTO contactRequests (s_firstname, s_lastname)

-- Example with a valid value:
-- The query is accepted.
INSERT INTO contactRequests (s_firstname, s_lastname, d_dateReceived)
VALUES ('John', 'Duff', '2026-09-01 14:35:12');

-- Example of a query with CURRENT_TIMESTAMP:
-- CURRENT_TIMESTAMP is used here as an explicit value, not the default.
-- The query is accepted.
INSERT INTO contactRequests (s_firstname, s_lastname, d_dateReceived)
VALUES ('John', 'Duff', CURRENT_TIMESTAMP);


SQL
-- Create the table
---- d_dateReceived is mandatory
---- NULL is forbidden
---- no default value is defined
---- Any INSERT/UPDATE query must explicitly provide d_dateReceived, otherwise it fails
---- Additional constraint: Dates prior to 2012 are prohibited
CREATE TABLE contactRequests (
   d_dateReceived DATETIME NOT NULL,
   CONSTRAINT chk_dateReceived
      CHECK (d_dateReceived >= '2012-01-01')
);

-- Modify the existing table
-- Will fail if even one row still contains NULL in d_dateReceived => Clean the table first.
---- d_dateReceived is mandatory
---- NULL is forbidden
---- no default value is defined
---- Any INSERT/UPDATE query must explicitly provide d_dateReceived, otherwise it fails
---- Additional constraint: Dates prior to 2012 are prohibited
ALTER TABLE contactRequests
ADD CONSTRAINT chk_dateReceived
CHECK (d_dateReceived >= '2012-01-01');



Tips when importing data


Import using sql_mode



 Click to sort columns
LevelDefinition methodLocationActual scopeImpactPersistenceRecommendations
1. Low level[mysqld]my.iniServer-wideAll connections
(after startup)
Yes
(on restart)
Preferred in production to enforce consistent rules and avoid permissive connections.
2. AdminSET GLOBAL sql_mode = ...SQL executed with admin privileges
(cmd > mysql)
Server-wide
(only for new connections)
New sessions onlyNo
(lost on restart)
Useful for an immediate change without editing the [mysqld] configuration.
3. SessionSET SESSION sql_mode = ...SQL executed by application/tool
(phpMyAdmin, HeidiSQL, etc.)
Current session
(one connection)
A single connectionN/A
(lives for the duration of the connection)
Suitable for one-off uses, imports, scripts.
4. Application-level (high level)INITSTMT=SET SESSION sql_mode=...DSN / ODBC connection stringCurrent session
(each time a connection is opened via this DSN)
Connections that use this DSNN/A
(re-applied on each new connection via this DSN)
Useful for standardizing the ODBC client.


Clean up after import


Search for invalid dates (zero dates)
SQL
-- The d_dateReceived field is of type Date.
-- The threshold 1000-01-01 covers dates that are technically storable,
-- but invalid according to the SQL standard.
SELECT *
FROM contactRequests
WHERE d_dateReceived = '0000-00-00 00:00:00'
   OR d_dateReceived < '1000-01-01';

  • either delete the affected rows
  • or replace them with a real business date (e.g. creation date, order date, etc.)
  • or replace them with NULL


Replace incorrect dates with NULL (zero dates)
SQL
UPDATE contactRequests
SET d_dateReceived = NULL
WHERE d_dateReceived = '0000-00-00 00:00:00'
   OR d_dateReceived < '1000-01-01';


Modify the schema (zero dates)



Tips when writing data


Do not provide an empty value

ASP CLASSIC
<%
'Specify NULL using a standard SQL query
'-	-	-	-	-	-	-	-	-	-	-	-
strSQL = "INSERT INTO contactRequests (d_dateReceived) VALUES (NULL)"
dbConn.Execute(strSQL)


'Specify NULL using a parameterized SQL query
'-	-	-	-	-	-	-	-	-	-	-	-
'Do not use vbNull: it is an internal VBScript constant type
Set paramCmd = Server.CreateObject("ADODB.Command")
Set paramCmd.ActiveConnection = dbConn
paramCmd.CommandText = "INSERT INTO contactRequests (d_dateReceived) VALUES (?)"
paramCmd.Parameters.Append paramCmd.CreateParameter("@d_dateReceived", adDBTimeStamp, adParamInput, , Null)
paramCmd.Execute
%>


Provide a date in ISO format

ASP CLASSIC
<%
'Return a date formatted for MySQL/MariaDB in the format "YYYY-MM-DD HH:MM:SS"
Function DateFormat_MySQL_MariaDB(byVal dtInput)

   'Parameter  Variable   Type          Description
   '---------  --------   ----          -----------
   '@param     dtInput    String/Date   Date or Date/Time (VBScript/ASP type "String" or "Date")
   '@return    dtOutput   String/Null   Date string formatted as "YYYY-MM-DD HH:MM:SS", or Null.

   Dim sYear, sMonth, sDay, sHour, sMinute, sSecond
   Dim dtOutput : dtOutput = Null
   
   'If the input can be converted to type "Date":
   If (IsDate(dtInput)) Then
      'Retrieve the date parts
      sYear   = CStr(Year(dtInput))
      sMonth  = Right("0" & Month(dtInput), 2)
      sDay    = Right("0" & Day(dtInput), 2)
      
      'Check if a time is present
      If ((Hour(dtInput) + Minute(dtInput) + Second(dtInput)) > 0) Then
         sHour   = Right("0" & Hour(dtInput), 2)
         sMinute = Right("0" & Minute(dtInput), 2)
         sSecond = Right("0" & Second(dtInput), 2)
      Else
         sHour   = "00"
         sMinute = "00"
         sSecond = "00"
      End If
      
      'Build the date string in ISO format for MySQL/MariaDB
      dtOutput = sYear & "-" & sMonth & "-" & sDay & " " & sHour & ":" & sMinute & ":" & sSecond
   Else
      dtOutput = Null 'Return Null if the input is not a valid date
   End If

   'Return
   DateFormat_MySQL_MariaDB = dtOutput

End Function 'DateFormat_MySQL_MariaDB



'= =  =  =  =  =  =
'Usage examples
'= =  =  =  =  =  =

Dim dateSource, datetimeSource, dateStringForSQL

'Ex. Handling a date in English
'-------------------------------
SetLocale(1033) 'Set LCID to English

'Set/read a source date (in English format) - of type vbString.
dateSource = "04/13/2026" 'ex. April 13

'Return the date, formatted for MySQL/MariaDB
'=> RETURNS : 2026-04-13 00:00:00
dateStringForSQL = DateFormat_MySQL_MariaDB(dateSource)


'Ex. Handling a date in French
'-----------------------------
SetLocale(1036) 'Set LCID to French

'Set/read a source datetime (in French format) - of type vbDate.
datetimeSource = #01/09/2026 14:35:12# 'ex. 1 septembre

'Return the date, formatted for MySQL/MariaDB
'=> RETURNS : 2026-09-01 14:35:12
dateStringForSQL = DateFormat_MySQL_MariaDB(datetimeSource)


'Define the database insertion query.
'Use the date already correctly formatted for MySQL/MariaDB.
strSQL = _
   "INSERT INTO contactRequests ( " & _
      "s_firstname, " & _
      "s_lastname, " & _
      "d_dateReceived " & _
   ") VALUES ( " & _
      "'John', " & _
      "'Duff', " & _
      "STR_TO_DATE('" & dateStringForSQL & "') " & _
   ") "

'Add to the database
dbConn.Execute(strSQL)
%>


Provide a date in a custom format

ASP CLASSIC
<%
'Define a datetime with an arbitrary/exotic format – of type vbString.
Dim datetimeSource : datetimeSource = "TheYear=2026 TheMonth=09 TheHour=14 TheSecond=12 TheDay=01 FinallyTheMinute=35"

'Define a mask/pattern that allows MySQL/MariaDB to understand the provided string.
'(contains placeholders %Y %m %d %H %i %s, that are recognized by MySQL/MariaDB)
Dim datetimeMask : datetimeMask = "TheYear=%Y TheMonth=%m TheHour=%H TheSecond=%s TheDay=%d FinallyTheMinute=%i"

'Define the insertion query
strSQL = _
   "INSERT INTO contactRequests (" & _
      "s_firstname, " & _
      "s_lastname, " & _
      "d_dateReceived " & _
   ") VALUES (" & _
      "'John', " & _
      "'Duff', " & _
      "STR_TO_DATE('" & datetimeSource & "', '" & datetimeMask & "') " & _
   ")"

'Add to the database
dbConn.Execute(strSQL)
%>




Let the SQL engine use the current date




Tips when reading data


Use parameterized queries


Handle dirty values

SQL
-- VARIANT 1 : More concise
-- Performance is equivalent between CASE and NULLIF, even on large volumes.
-- CAST() has no impact in terms of performance.
-- *  *  *  *  *
-- Read from the "d_date" field of type DATETIME
-- Ensure that the data is a valid date
-- Returns NULL otherwise
SELECT
   CAST(
      NULLIF(
         IF(d_date < '1000-01-01', NULL, d_date),
         '0000-00-00 00:00:00'
      )
   AS DATETIME) AS d_date_safe
FROM contactRequests

-- VARIANT 2 : More readable
-- Performance is equivalent between CASE and NULLIF, even on large volumes.
-- CAST() has no impact in terms of performance.
-- *  *  *  *  *
-- Read from the "d_date" field of type DATETIME
-- Ensure that the data is a valid date
-- Returns NULL otherwise
SELECT
   CAST(
      CASE
         WHEN d_date = '0000-00-00 00:00:00' THEN NULL
         WHEN d_date < '1000-01-01'          THEN NULL
         ELSE d_date
      END
   AS DATETIME) AS d_date_safe
FROM contactRequests


SQL
-- Read from the "d_date_txt" field of type VARCHAR
-- Attempt to convert the string to a date according to the specified pattern
----- Will fail at the first instance of data that does not match the pattern!
SELECT
   STR_TO_DATE(d_date_txt, '%Y-%m-%d %H:%i:%s') AS d_date_safe
FROM myTable;


SQL
SELECT d_date FROM myTable WHERE d_date IS NOT NULL



Read a date in a custom format

ASP CLASSIC
<%
'We want to retrieve the date in the following exotic format: YYYY/MM hh:ss
'   Using the DATE_FORMAT() function slows down your query.
'   Therefore, it will be more efficient to read the raw data from MySQL/MariaDB,
'   then use ASP/VBScript to extract parts from it, then format it back.
Dim dateMask : dateMask = "%Y/%m %H:%i"

'Define the reading/retrieval request
Dim strSQL : strSQL = "SELECT DATE_FORMAT(contactRequests.d_dateReceived, '" & dateMask & "') AS myDate FROM contactRequests "

'Open database connection
Set dbConn = Server.CreateObject("ADODB.Connection")
dbConn.Open dbConnString

'Open the Recordset in "Forward-Only" mode via .Execute()
Set rs = dbConn.Execute(strSQL)
%>


Work around zero dates







At the service of your ASP Classic





Privacy preferencesYour privacy preferences

NOTE: Your changes will be applied from the next page you will visit/load.

Your privacy is precious: we respect it.

By using this website, you consent that we use technologies such as anonymous statistics and cookies to improve your browsing experience on our site, customise content, and analyse our traffic. This anonymous information may be shared with our trusted social media and analytics partners.

  • We do not collect any nominative data.
  • We do not store any password.
  • We use a high-end secure connection.