CURRENT_DATE/CURDATE() not working as default DATE value
Why CURRENT_DATE/CURDATE() Don't Work as Default DATE Values in MySQL

Explore the common pitfall of using CURRENT_DATE()
or CURDATE()
directly as default values for DATE
columns in MySQL and learn the correct approaches.
A frequent challenge faced by developers working with MySQL is attempting to set CURRENT_DATE()
or CURDATE()
as the default value for a DATE
column. While these functions correctly return the current date, MySQL's SQL standard compliance prevents their direct use in DEFAULT
clauses for DATE
type columns. This article delves into why this limitation exists and provides practical solutions to achieve the desired behavior.
The MySQL Limitation Explained
MySQL adheres to the SQL standard, which dictates that DEFAULT
values for columns must be constants. Functions like CURRENT_DATE()
, CURDATE()
, NOW()
, or CURRENT_TIMESTAMP()
are dynamic; their return values change over time. While TIMESTAMP
and DATETIME
columns have special provisions for CURRENT_TIMESTAMP
(or NOW()
) as a default, DATE
columns do not. This distinction is a common source of confusion.
CURRENT_DATE()
as a default is Invalid default value for 'your_date_column'
.flowchart TD A[Attempt to set DATE column default] --> B{Is default value a constant?} B -- No --> C[Is column TIMESTAMP/DATETIME?] C -- No --> D["Error: Invalid default value (e.g., CURRENT_DATE())"] C -- Yes --> E[Is default CURRENT_TIMESTAMP/NOW()?] E -- Yes --> F[Allowed: Dynamic default for TIMESTAMP/DATETIME] B -- Yes --> G[Allowed: Constant default for DATE]
Decision flow for MySQL DEFAULT value validation
Solution 1: Using Triggers for Dynamic Defaults
The most robust and recommended way to set a dynamic default for a DATE
column is by using a BEFORE INSERT
trigger. A trigger allows you to execute SQL statements automatically before or after a DML (Data Manipulation Language) event, such as an INSERT
. This approach ensures that the date_created
column is populated with the current date whenever a new row is inserted, without requiring the application to explicitly provide it.
CREATE TABLE events (
event_id INT PRIMARY KEY AUTO_INCREMENT,
event_name VARCHAR(255) NOT NULL,
event_date DATE,
date_created DATE
);
DELIMITER //
CREATE TRIGGER set_date_created_before_insert
BEFORE INSERT ON events
FOR EACH ROW
BEGIN
IF NEW.date_created IS NULL THEN
SET NEW.date_created = CURDATE();
END IF;
END;//
DELIMITER ;
-- Test the trigger
INSERT INTO events (event_name, event_date) VALUES ('Meeting', '2023-10-26');
INSERT INTO events (event_name, event_date, date_created) VALUES ('Workshop', '2023-11-15', '2023-01-01');
SELECT * FROM events;
Creating a trigger to set date_created
to CURDATE()
on insert
IF NEW.date_created IS NULL
condition in the trigger is crucial. It allows you to explicitly provide a date_created
value if needed, otherwise, it defaults to CURDATE()
.Solution 2: Application-Level Handling
Another viable approach is to handle the default date assignment at the application level. When inserting new records, if the date_created
field is not explicitly provided by the user, your application code can automatically supply CURRENT_DATE()
(or its equivalent in your programming language) before sending the INSERT
query to the database. This shifts the responsibility from the database to the application.
Python (SQLAlchemy)
from datetime import date from sqlalchemy import create_engine, Column, Integer, String, Date from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class Event(Base): tablename = 'events' event_id = Column(Integer, primary_key=True) event_name = Column(String(255), nullable=False) event_date = Column(Date) date_created = Column(Date, default=date.today)
def __repr__(self):
return f"<Event(name='{self.event_name}', created='{self.date_created}')>"
engine = create_engine('mysql+mysqlconnector://user:password@host/database') Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine) session = Session()
Insert without specifying date_created
new_event_1 = Event(event_name='Team Sync', event_date=date(2023, 10, 27)) session.add(new_event_1) session.commit()
Insert specifying date_created
new_event_2 = Event(event_name='Client Demo', event_date=date(2023, 11, 10), date_created=date(2023, 1, 1)) session.add(new_event_2) session.commit()
print(session.query(Event).all())
PHP (PDO)
PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; try { $pdo = new PDO($dsn, $user, $pass, $options); } catch (\PDOException $e) { throw new \PDOException($e->getMessage(), (int)$e->getCode()); } // Create table if it doesn't exist (for demonstration) $pdo->exec("CREATE TABLE IF NOT EXISTS events ( event_id INT PRIMARY KEY AUTO_INCREMENT, event_name VARCHAR(255) NOT NULL, event_date DATE, date_created DATE );"); // Insert without specifying date_created $stmt = $pdo->prepare("INSERT INTO events (event_name, event_date, date_created) VALUES (?, ?, ?)"); $stmt->execute(['Project Review', '2023-10-30', date('Y-m-d')]); // Insert specifying date_created $stmt->execute(['Product Launch', '2023-12-01', '2023-01-01']); $stmt = $pdo->query("SELECT * FROM events"); while ($row = $stmt->fetch()) { print_r($row); } ?>Solution 3: Using a DATETIME
or TIMESTAMP
Column (If Applicable)
If your requirement is simply to record when a row was created and the time component is acceptable (or even desirable), consider using a DATETIME
or TIMESTAMP
column instead of DATE
. These types do support CURRENT_TIMESTAMP
(or NOW()
) as a default value directly in the column definition, making it a very convenient option if the exact date without time isn't a strict requirement.
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Or for TIMESTAMP, which also supports auto-update
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT,
order_total DECIMAL(10, 2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO products (product_name, price) VALUES ('Laptop', 1200.00);
INSERT INTO orders (customer_id, order_total) VALUES (101, 250.50);
SELECT * FROM products;
SELECT * FROM orders;
Using DATETIME
or TIMESTAMP
with CURRENT_TIMESTAMP
as default