pythonsqldatedatetimeapsw

Insert datetime entry into table with TIMESTAMP data type


I am trying to create a system (with a discord bot, but that's not relevant to this) where it lists infractions of a user, like when it happened, where, why, etc. and I want a "date" datatype that logs the timestamp that it happened.

I tried having the DATE datatype to be "timestamp" (as well as "datetime", but the same error happens)

conn1 = apsw.Connection('./dbs/warns.db')
warns = conn1.cursor()

warns.execute(
    """
    CREATE TABLE IF NOT EXISTS warns
    (id INTEGER PRIMARY KEY AUTOINCREMENT,
    date timestamp,
    server string,
    user string,
    author string,
    reason string)
    """
)

def add_warn(guild: str, user: str, author: str, reason):
    now = datetime.datetime.utcnow()
    with conn1:
        warns.execute("INSERT INTO warns (date, server, user, author, reason) VALUES (?, ?, ?, ?, ?)", (now, guild, user, author, reason))

I end up getting a TypeError: Bad binding argument type supplied - argument #1: type datetime.datetime error


Solution

  • From the syntax of the create table statement (AUTOINCREMENT without an underscore) and the apsw tag, I suspect that you are using a SQLite database.

    If you are looking to insert the current timestamp to a timestamp column, my first suggestion is to do it directly in SQL, instead of using a variable generated in python. In sqlite, CURRENT_TIMESTAP gives you the current date/time as a timestamp:

    warns.execute(
        "INSERT INTO warns (wdate, server, user, author, reason) VALUES (CURRENT_TIMESTAMP, ?, ?, ?, ?)", 
        (guild, user, author, reason)
    )
    

    Another option, that would furthermore simplify your code, is to set a default for the timestamp column when creating the table. Then, you can just ignore this column when inserting, and rest assured that the correct value will be assigned:

    warns.execute(
        """
            CREATE TABLE IF NOT EXISTS warns (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                wdate timestamp DEFAULT CURRENT_TIMESTAMP,
                server string,
                user string,
                author string,
                reason string
            )
        """
    )
    
    def add_warn(guild: str, user: str, author: str, reason):
        with conn1:
            warns.execute(
                "INSERT INTO warns (server, user, author, reason) VALUES (?, ?, ?, ?)", 
                (now, guild, user, author, reason)
            )
    

    Note: date is not a sensible column name, since it clashes with a datatype name. I renamed it wdate in all the above code.