MS SQL Python Datetime大于,但不等于'>'返回结果为'>='

2024-10-08 20:23:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图查询Microsoft SQL数据库,以获取在上一个循环中返回的日期时间之后的所有记录。我使用“>;”运算符,但我看到的结果是“>;=”(大于或等于)。在

Python(3.6.5 Win10)脚本:

import pyodbc  # version 4.0.24
import time
import datetime
import json
con = pyodbc.connect("DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=mydb;UID=myuid;PWD=mypwd")
cur = con.cursor()
i = 0
lastDatetime = datetime.datetime.strptime('01Jan1970', '%d%b%Y')
while i < 60:
    print("{0}: SELECT * FROM dbo.Data WHERE datetime > '{1}'".format(str(i), lastDatetime))
    cur.execute("SELECT * FROM dbo.Data WHERE datetime > ?", lastDatetime)
    rows = cur.fetchall()
    for k, v in enumerate(rows):
        jsonMsg = json.dumps({
            "transaction_id": v[1],
            "plu": v[2].strip(),
            "qty": int(v[3]),
            "dateTime": str(v[4])
        }, separators=(',', ':'))
        print(str(jsonMsg))
        lastDatetime = v[6]
        print("lastDatetime set to: {0}".format(lastDatetime))
    i = i + 1
    time.sleep(5)

产生:

^{pr2}$

我在SQL Server Management Studio中运行查询,得到预期结果:

SELECT * FROM dbo.Data WHERE datetime > '2018-08-01 10:48:47.653' 

不返回记录。在

为了得到预期的结果,我在python脚本中缺少了什么或者应该做些什么修改?在

谢谢。在

编辑: 将“”添加到datatime前后的sql字符串的打印中。对结果没什么影响。在


Tags: fromimportgt脚本sqldatadatetime记录
2条回答

我把最后一次加上1毫秒,并把“>;”改为“>;=”,就解决了这个问题。由于毫秒是当前MS-SQL中最小的时间增量,因此该方法不应丢失任何数据。在

我怀疑这与Python处理浮点数有关,但不能肯定的是,将1毫秒的浮点数加到秒数部分并没有完全增加它。在

修订代码:

import pyodbc  # version 4.0.24
import time
import datetime
import json
con = pyodbc.connect("DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=mydb;UID=myuid;PWD=mypwd")
cur = con.cursor()
i = 0
lastDatetime = datetime.datetime.strptime('01Jan1970', '%d%b%Y')
while i < 60:
    print("{0}: SELECT * FROM dbo.Data WHERE datetime >= '{1}'".format(str(i), lastDatetime))
    cur.execute("SELECT * FROM dbo.Data WHERE datetime >= ?", lastDatetime)
    rows = cur.fetchall()
    for k, v in enumerate(rows):
        jsonMsg = json.dumps({
            "transaction_id": v[1],
            "plu": v[2].strip(),
            "qty": int(v[3]),
            "dateTime": str(v[4])
        }, separators=(',', ':'))
        print(str(jsonMsg))
        lastDatetime = v[6]
        # work around a bug with datetime > returning as if >=
        lastDatetime = lastDatetime + datetime.timedelta(milliseconds=1)
        print("lastDatetime set to: {0}".format(lastDatetime))
    i = i + 1
    time.sleep(5)

注意到您打破了2016年的变化:

Under database compatibility level 130, implicit conversions from datetime to datetime2 data types show improved accuracy by accounting for the fractional milliseconds, resulting in different converted values. Use explicit casting to datetime2 datatype whenever a mixed comparison scenario between datetime and datetime2 datatypes exists. For more information, refer to this Microsoft Support Article.

Breaking Changes in SQL Server 2016

问题是您的表仍然使用旧的datetime数据类型。这是一种很奇怪的类型。它没有ms分辨率。它的分辨率实际上是1/300秒。所以实际的存储值并不总是看起来的那样。存储是不精确的,就像浮点数一样。在

新的better datetime2具有更高的精度,并且始终存储十进制小数秒。无论如何,SQL 2016改变了datetime转换为datetime2的方式,其副作用是使涉及隐式转换的比较有时中断。在

要解决此问题,请将表上的数据类型更改为datetime2(3),以获得1ms的精度。或者强制参数为datetime,而不是datetime2。我不知道pyodbc是否允许这样做,但是您可以很容易地在查询中强制转换:

cur.execute("SELECT * FROM dbo.Data WHERE datetime >= cast(? as datetime)", lastDatetime)

现在,不是将表列转换为datetime2,而是将参数值转换为datetime,比较工作如预期。在

或者将数据库兼容性级别降低到120。在

相关问题 更多 >

    热门问题