0

我试图了解我必须更新的以下 Coldfusion/MySQL 查询中发生了什么(而且我正处于 CF/MySQL 的第一个月)。

我在搜索之前运行了一个查询,它设置了变量pl (pricelists),如下所示:

<cfif variables.module IS "yes"> 
  <cfquery datasource="ds" name="qp">
      <!--- selects pricelist and seller --->
  </cfquery>
  <cfset variables.pl = "LEFT JOIN pricelist p ON ">
  <cfoutput query="qp" >
    <cfif qp.preislist IS ''>
        <cfset variables.pl= variables.pl & '(p.iln = a.iln AND p.preislist = "AAA" AND p.ean = a.ean AND p.iln = "#qp.seller#") OR '>
    <cfelse>
        <cfset variables.pl= variables.pl & '(p.iln = a.iln AND p.preisliste = "#qp.preislist#" AND p.ean = a.ean AND p.iln = "#qp.seller#") OR '>
    </cfif>
  </cfoutput>
  <cfset variables.pl = variables.preislisten & "(1=0)">
</cfif>

然后将其“移植”到搜索查询中,这增加了我的困惑,如下所示:

<cfquery datasource="ds" name="getArt">
    SELECT a.* <cfif variables.module IS "yes">, p.ek, p.vk, p.waehrung, p.onlinepreis</cfif>
    FROM artdata a
    <cfif variables.module IS "yes">
        <cfqueryparam cfsqltype="cfsql_varchar" value="#variables.pl#"> 
    </cfif>
    ....

很多问题:
- 不需要 cfparam 查询字段,例如qp.seller,或者有吗?
- 我不应该总是像在artdata AS a中那样使用 ALIAS 而不是只使用artdata a吗?
- 我可以像这样选择p.ek, p.vk, ...尽管价格表稍后将仅通过变量variables.pl声明(即LEFT JOIN pricelist p ON ...)
- 这是怎么回事( 1=0)? 它的目的是什么?(3=2), (1=2) 的同上。

感谢您的启发!

4

3 回答 3

3

没有必要cfparam查询字段如qp.seller,还是有?

不是 cfparam,而是 cfqueryparam - 这是执行不同任务的两个不同标签。

使用 cfqueryparam 有两个关键原因:

1) 出于安全考虑 - 如果输入可能最初来自任何第三方,或者如果您不能保证输入是已知值,请使用 cfqueryparam 确保不会发生 SQL 代码注入(有意或无意)。

2) 性能方面——查询参数会产生一个执行计划,该计划可以被缓存并应用于多个查询(即参数变化的地方),因此通常会提高性能。

如果 qp.seller 是保证安全的数字外键,则您不需要它来确保安全,但它仍然可能从性能方面产生有益影响。

一般来说,如果有疑问,请使用它

(偶尔有人声称它会导致糟糕的执行计划,从而导致性能更差,但我对这些说法持谨慎态度,并且无论如何都必须根据具体情况进行处理 - 安全性很重要.)


我不应该总是像在 artdata AS a 中那样使用 ALIAS 还是只使用 artdata a?

如果你更喜欢打字。:)

表名的 AS 关键字没有区别/好处。


我可以像这样选择 p.ek, p.vk, ...

是的,这会奏效。

可能希望将它们放在多行上以使其更具可读性。


虽然 pricelist 表只会在稍后通过变量 > variables.pl 声明(即 LEFT JOIN pricelist p ON...)

这是一个不正确的假设。

使用 cfqueryparam 专门防止 SQL 代码被注入,这是您在此处尝试使用它执行的操作。

您应该将生成的 SQL 直接输出到将使用它的 cfquery 标记中,而不是创建 variables.pl。

(如果您不确定我的意思,我可以为此举个例子吗?)


(1=0) 怎么了?它的目的是什么?(3=2), (1=2) 的同上。

正如 Romain 的评论所解释的,这是一种常见的错误说法,用于动态查询。括号是可选的。

然而,更常见的是将它放在开头- 即WHERE 1=0JOIN 1=0- 然后让动态语句开始OR ...

于 2012-05-21T12:53:09.627 回答
2

- 不需要cfparam查询字段如qp.seller,还是有?

首先,这是cfqueryparam,不是cfparamcfqueryparam用于数据清理。cfparam是为了确保存在具有某种值的变量。有必要使用吗?如果您明确创建/设置 variables.pl,则不。但这仍然是一个很好的做法。如果您或其他人稍后更改设置代码,则对数据进行 cfqueryparam-ing 可确保数据完整性。它还可以帮助您一目了然地了解变量包含的数据类型。

- 我不应该总是在 artdata AS a 中使用 ALIAS 与仅使用 artdata a 吗?

据我了解,你应该。我使用的所有数据库都支持该tablename alias语法,但我相信ANSI 标准是使用AS,这将使您的代码更具可移植性。

- 我可以像这样选择 p.ek, p.vk, ... 虽然价格表稍后将通过变量 variables.pl 声明(左连接价格表 p ON...)

是的。这是相当普遍的(至少在我工作的地方)。

- (1=0) 怎么了?它的目的是什么?(3=2), (1=2) 的同上。

这在 Romain 的评论中得到了很好的回答。这是一个强制的真/假值。它通常在动态生成 SQL 语句时使用,以确保至少WHERE生成一个子句。

于 2012-05-21T12:58:37.710 回答
2

关于“不需要 cfparam 查询字段,例如 qp.seller,或者是否存在?”:我还没有看到提到的一件事是 cfqueryparam 仅在 cfquery 标记的上下文中有效。由于您在 cfquery 标记上下文之外构建 SQL 块,因此您将无法在该处为 qp.seller 使用 cfqueryparam。因此,您有一些选择——

  1. 将您的 SQL 代码移动到您的 cfquery 块中并使用 cfqueryparam。
  2. 在您的数据库中创建一个以 qp.seller 作为参数的存储过程或函数。
  3. 使用某种数据验证正则表达式来验证#qp.seller# 是一个有效值。
  4. 什么都不做,并相信由于您可以控制用作查询输入的数据源,因此您不必担心 SQL 注入(但是您仍然会失去可能的性能改进) .

其他海报已经很好地回答了你的其他问题——我没有什么要补充的了。

于 2012-05-21T17:27:45.017 回答