-1

编辑..抱歉,列是字符串 db 是我相信的 mysql。

我正在尝试进行查询,但不确定如何编写,目前我有

   adoquery1.SQL.Add('SELECT * FROM workorder WHERE siteid=''p203'' AND worktype = ''CM'' AND reportdate > '''+edit1.text+'''') ;

它使用日期分级器获取数据,然后是edit1.text中的日期,我怎么能说获取相同的数据但reportdate在两个日期之间?

例子

siteid = p203   AND
worktype = CM   AND
reportdate between edit1.text and edit2.text
4

2 回答 2

9

许多数据库都有 BETWEEN 运算符,否则您始终可以使用(reportdate >= :date1 and reportdate <= :date2).

SELECT * FROM workorder 
WHERE siteid = :siteId AND worktype = :workType
AND reportdate between :date1 and :date2

或者,

SELECT * FROM workorder 
WHERE siteid = :siteId AND worktype = :workType
AND (reportdate >= :date1 and reportdate <= :date2)

第二种形式让您可以更好地控制是使用封闭-开放(包括开头)还是封闭(包括两端)边界。

理想情况下,您将使用绑定参数——对语句中的每个参数使用 :name 占位符,并将值绑定到它们。(在我们使用的其他语言中?)。

除了通过引用防止 SQL 注入黑客和错误之外,这对于DATEorTIMESTAMP数据类型也可以更可靠。日期应正确解析,字符串应在应用层转换为此类,而不是作为字符串存储在数据库中。

于 2013-09-11T10:26:52.250 回答
7
adoquery1.SQL.Add('SELECT * FROM workorder'); 
adoquery1.SQL.Add('WHERE siteid=:SiteId AND'); 
adoquery1.SQL.Add('worktype = :WorkType AND'); 
adoquery1.SQL.Add('reportdate between :StartDate and :EndDate ');

adoquery1.Parameters[0].Value := 'p203';
adoquery1.Parameters[1].Value := 'CN';
adoquery1.Parameters[2].Value := Edit1.Text;
adoquery1.Parameters[3].Value := Edit2.Text; 

这个代码片段的要点是,使用参数解决问题就像“内联”你的 Sql 一样容易。

主要好处是您的数据会自动清理并具有两种效果 - i) 您可以免受 Sql 注入攻击,并且 ii) 您不必对数据执行预处理 - 例如,如果姓氏是“O'Flannagan”,则将其作为内联传递value 需要一个预处理函数,例如RemoveApostrophes().

在 Oracle 等服务器上还有一个额外的好处——Oracle 优化器将缓存查询计划。如果它遇到相同的 Sql 它将使用缓存的计划,因此性能更好。它可以将参数识别为“相同”,但如果您每次都提供不同的 Sql,则不能。(我不能特别评论其他 RDBMS,但如果同样适用,我不会感到惊讶。)

在我看来,这种方法至少和另一种方法一样可读。

于 2013-09-11T10:26:36.987 回答