结果的顺序在多语句查询中显然无缘无故地改变了
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 使用量以及保存查询计划的内存使用量产生很大影响。
我是 运行 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 使用量以及保存查询计划的内存使用量产生很大影响。