Python:SQL Server使用datetime插入多个值(从字符串转换日期和/或时间时转换失败)

Python:SQL Server使用datetime插入多个值(从字符串转换日期和/或时间时转换失败),python,sql-server,datetime,sql-insert,pyodbc,Python,Sql Server,Datetime,Sql Insert,Pyodbc,我试图在python中的数据库表(SQL server)中插入多行: def write_to_database(values): conn = pyodbc.connect("Driver={SQL Server};" "Server=xxxx.database.windows.net;" f"Database={database};&qu

我试图在python中的数据库表(SQL server)中插入多行:

def write_to_database(values):
    conn =  pyodbc.connect("Driver={SQL Server};"
                        "Server=xxxx.database.windows.net;"
                        f"Database={database};"
                        "UID=user;"
                        "PWD=password;")
    cursor = conn.cursor()
    cursor.executemany("insert into KeyFigures (DateTime, Parameter, CommulativeTime, Value) values (?,?,?,?)", values)
    conn.commit()
    return()

date = datetime.datetime.now()
atom = date.strftime("%Y-%M-%d") + " " + date.strftime("%H:%M:%S") + ".4526800"

values = ([datetime.datetime.now().isoformat(), 1, "NULL", 2],[datetime.datetime.now().isoformat(), 1, "NULL", 47],[datetime.datetime.now().isoformat(), 1, "NULL", 78])

write_to_database(values)
我尝试了多种日期时间格式、字符串组合等,例如:

datetime.datetime.now().isoformat() 
atom
"2020-02-23 11:30:53.4526800"
"2020-02-23T11:30:53.4526800" 
但我一直收到同样的错误:

line 50, in write_to_database
    cursor.executemany("insert into KeyFigures (DateTime, Parameter, CommulativeTime, Value) values (?,?,?,?)", values)
pyodbc.DataError: ('22007', '[22007] [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting date and/or time from character string. (241) (SQLExecDirectW)')
在SSMS中,以下工作:

INSERT INTO KeyFigures (DateTime, Parameter, CommulativeTime, Value) VALUES ('2020-02-23 11:30:53.4526800',2,null,21)
如何解决此错误

*****编辑****

@非常感谢你。这已经非常有用了,但在我的代码中不起作用。我仍然收到同样的错误。我还尝试插入一行,这段代码可以工作(使用execute而不是executemany):


如果报价之间没有日期,它就不起作用。这也是执行官的问题吗?当我把问号放在qoutes(“?”或“?”)之间时,给出的错误是只给出了3个参数,而不是4个。

正如我在评论中提到的,如果使用强类型数据类型(因此不要将其转换为字符串),python和pyodbc将很好地处理这个问题。但是,我也建议更新到,而不是使用旧的本机SQL Server驱动程序。我还使用将光标放在一个
中,这样它就可以优雅地靠近

对于我用下面的定义创建的一个表,这很好,插入了两行,具有正确的日期和时间值:

创建表dbo.TestDateTable(i int,dt datetime2(7));
导入日期时间,pyodbc def将_写入_数据库(值): conn=pyodbc.connect(“驱动程序={ODBC驱动程序17 for SQL Server};” “服务器=xxxx.database.windows.net;” “数据库={Database};” “UID=用户;” “PWD=密码;”) 使用conn.cursor()作为光标: cursor.executemany(“插入到dbo.TestDateTable(i,dt)值(?,);”中,值) 康涅狄格州提交 返回() date=datetime.datetime.now() 值=([1,日期],[2,日期]) 将\写入\数据库(值)
不要将它们转换为字符串,将参数作为强类型数据和时间值传递给
游标,python可以很好地处理它。此外,您应该真正使用“不要使用动态SQL”来注入列值。使用
插入…值(?,…
并在元组中传递参数值(对于
.execute
)或元组列表(对于
.executemany
)。这是一个很好的建议。但是,请注意,使用上下文管理器(
块)退出时不会自动关闭光标。详细信息。谢谢@GordThompson。因此,您是否建议使用
连接()在
外部/内部显式关闭
光标。关闭()
是多余的;除非我读错了链接。这个问题会被详细讨论。@Mogo,我编辑了我的开始文章。我尝试了你的代码,但没有成功。@Loesviser你的尝试没有参数化;你正在注射。这是一个主要的安全缺陷。请再次查看我的答案。如果你注射了,那么是的,你将不得不问uote值,但不应进行注入,因为这是一个安全缺陷。
def write_to_database(date,parameter,cummulativeTime,value):
    conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};"
                        "Server=xxxx.database.windows.net;"
                        f"Database={database};"
                        "UID=user;"
                        "PWD=password;")
    with conn.cursor() as cursor:
        cursor.execute(f"INSERT INTO dbo.KeyFigures (DateTime, Parameter, CommulativeTime, Value) values ('{date}',{parameter},{cummulativeTime},{value})")
        conn.commit()
    return()


date = datetime.datetime.now()

write_to_database(date, 1, "NULL", 43)