结果的顺序在多语句查询中显然无缘无故地改变了

The order of the results is changed for apparently no reason in a multi statement query

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

DECLARE @mydate DATETIME = '2021-02-08'

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

在Python这边,我正在执行通常的

crsr.execute(sql, field)

让我感到困惑的是它 returns 所有结果 并且它忽略了条件 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 注入的风险,这通常不是一个好主意。

I note that pymssql driver does support named parameters

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


当这个值作为一个合适的参数通过时(当使用一个好的 SQL 驱动程序时),参数被“嗅探”,编译器将根据第一个 运行 的查询。如果有一个常用的值,这会很有用。


如果值在局部变量中,则不使用参数嗅探,编译器使用该谓词的平均基数。这可能比“嗅探”更好或更坏。


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

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