使用pyodbc查询SQL Server为何仅返回100000行而非预期120000行
这事儿我之前也碰到过类似的情况,咱们一步步排查可能的原因:
会话级别的行限制设置(最常见)
SQL Server里的SET ROWCOUNT命令会限制当前会话中所有SELECT语句返回的最大行数,哪怕你执行count(*)也会受影响。如果之前有代码或者操作执行过SET ROWCOUNT 100000,那后续所有查询都会被卡到10万行。
排查方法:执行DBCC USEROPTIONS查看当前会话的配置,看看有没有ROWCOUNT相关的设置。解决办法是在查询前执行SET ROWCOUNT 0(0表示取消限制),然后再执行你的查询。pyodbc连接字符串的限制
检查你的数据库连接字符串里有没有设置MAXROWS参数,比如DRIVER={ODBC Driver 17 for SQL Server};SERVER=...;MAXROWS=100000。这个参数会强制限制所有查询返回的行数,不管你用fetchall()还是直接查询。如果有这个参数,删掉它就行。实际表数据确实只有10万行(预期偏差)
你说表“应该”有12万行,但可能实际数据已经被删除、归档,或者统计信息过时导致你误以为有12万行。可以试试这几个操作:- 执行
sp_spaceused 'your_table_name',查看rows字段的实际行数; - 执行
UPDATE STATISTICS your_table_name更新统计信息,然后再查count(*); - 直接查
select top 10 * from your_table order by some_unique_column desc,看看最新的行是不是符合你的预期,有没有缺失的批次。
- 执行
游标类型的特殊限制(可能性较低)
pyodbc默认创建的是静态游标(static cursor),一般不会有行数限制,但如果你手动指定了其他游标类型(比如只进游标forward-only),某些特殊场景下可能会有问题?不过这种情况很少见,你可以检查下创建游标的代码,是不是用了类似conn.cursor(pyodbc.CURSOR_FORWARD_ONLY)这类设置?如果是,改成默认的静态游标试试。
另外,你提到用select * from table except top X只返回10万-X行,这进一步说明问题出在查询本身的返回行数限制,而不是fetchall()方法的问题——因为fetchall()只是把查询返回的所有结果取出来,它不会主动截断数据。
内容的提问来源于stack exchange,提问作者epattaro

