在多语句查询中,结果的顺序被毫无理由地改变



我正在运行Python pyodbc对SQL Server。这里有一个非常复杂的查询,我将其最小化为

DECLARE @mydate DATETIME = '2021-02-08'
SELECT * 
FROM atable 
WHERE adate = @mydate AND afield = ?

在Python端,我执行的是常规的

crsr.execute(sql, field)

令我困惑的是,它返回所有结果,它忽略了条件afield = field,没有其他错误,但有一个奇怪的顺序,所以当我绘制图形时,它非常困惑!为什么会这样呢?(编辑当然我应该加上ORDER BY)

我已经用一个初始

固定了代码
DECLARE @myfield VARCHAR(32) = ?

后面跟着以afield=@myfield结尾的where条件,现在它像预期的那样工作了:即使我没有引入显式的ORDER BY,顺序也是正常的。

换句话说,除了最终正确的修复是添加ORDER BY之外,例如

SELECT * 
FROM atable 
WHERE adate = @mydate AND afield = ?
ORDER BY id

我想知道为什么引入上述变化足以改变顺序。

因为您的SQL连接驱动程序似乎不支持适当的参数,所以它将参数嵌入为文本。我不知道它的消毒和转义方法有多好,但由于SQL注入的风险,这通常不是一个好主意。

我注意到pymssql驱动程序支持命名参数

可能发生的情况是,当编译器可以看到您想要使用的确切值时,它将计算可能匹配的行数("基数")的统计信息,因此它可能根据可用的索引选择不同的访问模式。


当该值作为一个适当的参数出现时(当使用一个好的SQL驱动程序时),该参数将被"嗅探",编译器将在第一次运行查询时使用基于该值的统计信息。如果有一个常用的值,这将是有益的。


如果值在一个局部变量中,则不使用参数嗅探,编译器使用该谓词的平均基数。这可能比"嗅探"好,也可能比"嗅探"差。


听起来嵌入值更好。但是不是的情况。

当嵌入值时,每个查询都是独立的,并且每次都必须重新编译。这会对执行时间和CPU使用以及保存查询计划的内存使用产生很大的影响。

最新更新