python - MS SQL 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)
产生:
0: SELECT * FROM dbo.Data WHERE datetime > '1970-01-01 00:00:00'
{"transaction_id":3201,"plu":"3","qty":1,"dateTime":"2018-08-01 10:45:40.560000"}
lastDatetime set to: 2018-08-01 10:45:40.560000
{"transaction_id":3202,"plu":"5","qty":1,"dateTime":"2018-08-01 10:45:51.563000"}
lastDatetime set to: 2018-08-01 10:48:47.653000
{"transaction_id":3230,"plu":"8","qty":2,"dateTime":"2018-08-01 10:48:47.653000"}
lastDatetime set to: 2018-08-01 10:48:47.653000
1: SELECT * FROM dbo.Data WHERE datetime > '2018-08-01 10:48:47.653000'
{"transaction_id":3230,"plu":"8","qty":2,"dateTime":"2018-08-01 10:48:47.653000"}
lastDatetime set to: 2018-08-01 10:48:47.653000
2: SELECT * FROM dbo.Data WHERE datetime > '2018-08-01 10:48:47.653000'
{"transaction_id":3230,"plu":"8","qty":2,"dateTime":"2018-08-01 10:48:47.653000"}
lastDatetime set to: 2018-08-01 10:48:47.653000
我在 SQL Server Management Studio 中运行查询,得到了预期的结果:
SELECT * FROM dbo.Data WHERE datetime > '2018-08-01 10:48:47.653'
不返回任何记录。
我缺少什么或我应该在 python 脚本中更改什么以获得预期的结果?
谢谢。
编辑:将 '' 添加到数据时间周围的 sql 字符串的打印中。对结果没有影响。
解决方案
您正在达到此处指出的 SQL 2016+ 的重大更改:
在数据库兼容级别 130 下,从 datetime 到 datetime2 数据类型的隐式转换通过考虑小数毫秒来显示提高的准确性,从而导致不同的转换值。只要存在 datetime 和 datetime2 数据类型之间的混合比较方案,就使用显式转换为 datetime2 数据类型。有关详细信息,请参阅此Microsoft 支持文章。
问题是您的表仍在使用旧datetime
数据类型。这是一种非常奇怪的类型。它没有毫秒分辨率。它的分辨率实际上是 1/300 秒。所以实际存储的值并不总是看起来像的那样。存储不精确,例如浮点数。
新的更好datetime2
的精度更高,并且始终存储十进制小数秒。无论如何,SQL 2016 改变了如何datetime
转换为datetime2
,这具有使涉及隐式转换的比较有时会中断的副作用。
要解决此问题,请将表上的数据类型更改为 datetime2(3) 以获得 1 毫秒的精度。或强制参数为日期时间,而不是日期时间2。我不知道 pyodbc 是否允许这样做,但您可以轻松地在查询中强制转换:
cur.execute("SELECT * FROM dbo.Data WHERE datetime >= cast(? as datetime)", lastDatetime)
现在,不是将表列转换为,datetime2
而是将参数值转换为datetime
,并且比较按预期工作。
或者将您的数据库兼容级别降低到 120。
推荐阅读
- c# - 为什么第一列在c#的控制台窗口上保持为空
- android - 在 Fragments Kotlin 中隐藏或显示操作栏
- android - 深度缓冲区在 android 上不起作用 Opengl es
- php - 如何在 mysql 查询中组合多个表并根据列的总数进行排名
- firebase - 关于 Firebase Rest Api 加入操作
- python - 如何使用来自另一个 kivy 应用程序的参数启动 kivy 应用程序
- flutter - Flutter Image_picker,sqflite 包在应用程序发布后无法正常工作,并且在调试模式下运行良好
- smalltalk - 如何处理 Spec 2 工具栏中的事件/检测按住 SHIFT 键?
- mysql - 如果存在具有所需值的所需文档,则更新表数据
- events - DDD 中的应用程序事件?