自动检查两个SQL查询在语义上是否相等

时间:2016-03-30 08:57:23

标签: sql

我有两个问题:

'UPDATE foo SET bar = baz WHERE a = b AND c = d'

'UPDATE foo SET bar = baz WHERE c = d AND a = b'

两者在语义上是相等的(它们都是相同的),但是简单的比较会声明它们是不同的,因为第一个具有a = b AND c = d而第二个使用c = d AND a = b

如何检查两个查询在语义上是否相等?

这是一个明显简单的例子,可以通过WHERE节点上的语法树的简单字母排序来解决。我对一种通用方法很感兴趣,它也可以解决更复杂的查询 - 即使是使用子查询。

进一步的限制是我无权访问数据库,只能使用查询的字符串。因此,运行查询是不可能的,因为它不会反映查询的相​​等性。

以上粗体文字的示例:

FooTable:

A |  B |  C
1 | xx | xx
2 | yy | zz

FooTable':( FooTable'在另一个数据库上是FooTable)

A |  B |  C
1 | xx | xx
2 | ee | zz
3 | ss | xx

运行查询的原因不会产生有效结果:

1)查询同一个数据库:

UPDATE FooTable SET B = 'rr' WHERE C = 'xx'

UPDATE FooTable SET B = 'rr' WHERE C = 'xx' OR B = 'ss'

两个查询的结果都完全相同,但通常不相等。

2)包含不同数据库(相同模式但数据不同)时的查询:

SELECT A,B,C FROM FooTable where C = 'xx'

SELECT A,B,C FROM FooTable' where C = 'xx'

这两个查询在语义上是平等的,但不会产生相同的结果。

1 个答案:

答案 0 :(得分:1)

这项任务确实不小。

实质上,您必须构建自己的查询解析器和优化器。这是优化器的任务 - 在执行计划中转换查询运算符,使得查询的最终结果对于基础表中的任何可能数据保持相同(考虑所有约束)。智能优化器能够为看起来非常不同的查询生成相同的计划(例如IN vs EXISTS),它们简化和统一WHERE子句中的逻辑条件,可以在执行时推送谓词树和做许多其他事情。

从头开始编写这样的优化器很难,但你可以查看现有的开源数据库(Postgres?),看看你是否可以从那里借一些东西。

另一种更实用的方法可能是利用现有数据库之一而不是运行查询,请求优化器返回生成的执行计划。然后,您可以比较执行计划,而不是比较原始SQL文本。如果计划相同,则原始查询是100%等效的。如果计划不同,优化程序仍然可能不足以推断出查询是等效的,但您必须接受错误否定的可能性。

我查看了几个不同的数据库,看看使用内置功能可以从优化器获得哪些信息。在任何情况下,生成的执行计划应该比原始SQL文本更加结构化,并且应该更容易自动比较它们。