从多个MySQL表中选择字段以及(1 = 2)是什么意思?

时间:2012-05-21 11:20:04

标签: mysql coldfusion

我正在尝试了解以下Coldfusion / MySQL查询中发生的事情,我不得不更新(我在CF / MySQL的第一个月)。

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

<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 中一​​样使用ALIAS而只使用 artdata a 吗?   - 我可以像这样选择 p.ek,p.vk,... 虽然价格表只会在稍后通过变量 variables.pl (正在< em> LEFT JOIN pricelist p ON ...)
  - (1 = 0)怎么了?它的目的是什么? Dito为(3 = 2),(1 = 2)。

感谢您的一些启示!

3 个答案:

答案 0 :(得分:3)

  

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

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

使用cfqueryparam有两个主要原因:

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

2)对于性能 - 查询参数导致执行计划可以缓存并应用于多个查询(即参数变化的地方),因此通常可以提高性能。

如果qp.seller是一个保证安全的数字外键,你不需要它来保证安全性,但它仍然可能从性能方面产生有益效果。

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

(偶尔会有人声称它会导致糟糕的执行计划导致性能下降,但我对这些声明持谨慎态度,并且在任何情况下都必须在个案中处理案例基础 - 安全很重要。)


  

我不应该像artdata AS一样使用ALIAS而只使用artdata a?

如果你喜欢打字更多。 :)

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


  

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

是的,那会有用。

可能喜欢将它们放在多行上,以使其更具可读性。


  

虽然价格表只会在稍后通过变量&gt;声明。 variables.pl(LEFT JOIN pricelist p ON ...)

这是一个不正确的假设。

使用cfqueryparam专门防止SQL代码被注入,这就是你在这里尝试使用它。

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

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


  

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

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

然而,更常见的是将它放在 start - 即WHERE 1=0JOIN 1=0 - 然后让动态语句从OR ...开始。< / p>

答案 1 :(得分:2)

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

首先,这是cfqueryparam,而不是cfparamcfqueryparam用于数据清理。 cfparam用于确保变量存在某种值。是否需要使用它?如果你明确地创建/设置variables.pl,那么没有。但它仍然是一个很好的做法。如果您或其他人稍后更改设置代码,则cfqueryparaming数据可确保数据完整性。它还可以帮助您一目了然地知道变量包含哪种数据。

- 我不应该像artdata AS一样使用ALIAS而只使用artdata吗?

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

- 我可以选择p.ek,p.vk,......就像这样,虽然pricelist表只会在稍后通过变量variables.pl声明(LEFT JOIN pricelist p ON ...)

是。这很常见(至少在我工作的地方)。

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

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

答案 2 :(得分:2)

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

  1. 将您的SQL代码移动到您的cfquery块并使用cfqueryparam。
  2. 在数据库中创建一个以qp.seller为参数的存储过程或函数。
  3. 使用某种数据验证正则表达式来验证#qp.seller#是否为有效值。
  4. 什么也不做,并且相信由于您可以控制用作查询输入的数据源,因此您不必担心SQL注入(您仍然会失去可能的性能改进) ,但是)。
  5. 其他海报已经很好地回答了你的其他问题 - 我没有更多的东西可以补充。