Firebird条件WHERE子句

时间:2014-05-05 06:54:45

标签: sql firebird

考虑到我有一个名为MYBOOKS的表包含超过一百万行的数据。 我想创建一个存储过程来返回一个特定的书,如果:提供BOOKID,或者,如果:BOOKID为0,则返回所有行。

所以这是我提出的SQL。

SELECT *
FROM MYBOOKS
WHERE :BOOKID = 0 OR BOOKID = :BOOKID

假设我想找:BOOKID = 102。 这可行,但它实际上扫描了数百万行,然后返回我正在寻找的一行数据。 有没有办法改进这个SQL?

请注意,上图已经简化。 在实际情况中,我在WHERE子句中有更多条件,我想让所有条件都是可选的。

SELECT *
FROM MYBOOKS
WHERE (:BOOKID = 0 OR BOOKID = :BOOKID) AND
      (:AUTHORID = 0 OR AUTHORID = :AUTHORID) AND
      (:TITLE = '' OR TITLE = :TITLE)
      //..... and so on

是否可以改进此SQL? 感谢。

1 个答案:

答案 0 :(得分:1)

使用条件WHERE是很昂贵的。 Firebird没有将这些评估短路,优化器无法以这种方式选择最佳方案。最好动态生成WHERE条件。

其他解决方案包括使用UNION,例如当您将第一个查询替换为:

SELECT *
FROM MYBOOKS
WHERE BOOKID = :BOOKID
UNION ALL
SELECT *
FROM MYBOOKS
WHERE :BOOKID = 0

优化器通常会为此查询选择更好的计划,但考虑到您要应用的多个条件,这可能是不可行的。