pymysql 插入datetime 使用f-string格式化产生的问题

439 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

问题

需要往数据库USER表里插入一条带有时间的数据

created_date=last_modified_date=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
knowledge_id=-1
print(created_date)
sql = f"""INSERT INTO USER(cid,created_date,last_modified_date) 
        VALUES ({cid},{created_date},{last_modified_date});"""
try:
    conn.execute_sql(sql)
    conn.commit()
except Exception as e:
    logger.error(f"mysql中插入:{cid}数据失败"
                 f"失败原因{e}")
    conn.rollback()
finally:
    conn.close_cursor()

运行就会报错,从报错的结果来看,是datetime上出现了问题。

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '16:41:46,2022-02-10 16:41:46)' at line 2")

但是实际上是使用python f-string 格式化的问题。

sql = f"""INSERT INTO USER(cid,created_date,last_modified_date) 
        VALUES ({cid},{created_date},{last_modified_date});"""

print一下

INSERT INTO USER(cid,created_date,last_modified_date)
            VALUES (24,2022-02-10 17:05:41,2022-02-10 17:05:41);

初看代码觉得没有什么问题,但是这里是一个天坑,需要注意一下。如果不适用f-string,运行正常的。

sql = "INSERT INTO USER(cid,created_date,last_modified_date) 
        VALUES ('%s','%s','%s');" %(cid,created_date,last_modified_date)

正常的format print一下

INSERT INTO USER(cid,created_date,last_modified_date)
            VALUES ('24','2022-02-10 17:05:41','2022-02-10 17:05:41');

在f-string{}前后增加''如下

sql = f"""INSERT INTO USER(cid,created_date,last_modified_date) 
        VALUES ({cid},'{created_date}','{last_modified_date}');"""

print一下

INSERT INTO USER(cid,created_date,last_modified_date)
            VALUES ('24','2022-02-10 17:05:41','2022-02-10 17:05:41');

结论

简单对比一下就能发现。

如果在f-string的{datetime}前面不加'',sql语句中datetime类型就不是string类型,mysql不认识这种类型,就会报错。(PS pymysql sql语句所有参数值能被解析成string类型) 补充一下: 后续我在写代码的过程中,发现不只是datetime类型会遇到这个问题,如果是string类型 传入空值,也需要加入''

remark=""
# 这个sql会报错
sql=f"""UPDATE USER SET remark={remark} WHERE id={cid};"""
# 这个sql是正常的
sql=f"""UPDATE USER SET remark='{remark}' WHERE id={cid};"""

建议在使用f-string中只要不是int类型,统统加上'',甚至为了省事所有类型都加上''。