你应该在MySQL请求中引用数字吗?

时间:2012-08-31 19:36:53

标签: php mysql request

使用简单的mysql而不是PDO或其他任何东西

会更专业和防错的方法

我通常喜欢这个

    $sql_request = "SELECT * 
                      FROM myusers 
                          WHERE user_id = {$user_id} 
                            AND email = '{$email_address}' 
                              LIMIT 0,1";

但是我应该引用{$user_id}吗?

即使我收到用户输入我也不引用数字,但是在处理之前我会检查ctype_digit()。

7 个答案:

答案 0 :(得分:6)

不,没有必要在数字文字周围加上引号。

使用MySQL,如果数字文字用单引号括起来就没问题;我认为我们经常看到这样做的原因是程序员不关心它是字符还是数字,而只是在所有文字中加上引号。

当引用值时,行为存在差异,而当值不是数字文字时,则不引用。例如,给定idINTEGER列,在此上下文中

... WHERE id = '1X'

此处的'1X'将被解释为值为1的文字数字,但在此上下文中

... WHERE id = 1X

此处的1X将被解释为列名,而不是数字文字。这可能会导致MySQL抛出“未知列”异常。

考虑如何解释这些差异......

... WHERE id = 'id'   -- 'id' will be interpreted as numeric literal value 0

... WHERE id = id     -- id will be interpreted as a column name

所以它真的归结为哪种行为最适合您的应用程序,当您希望被解释为数字文字时,不是数字。


我个人的偏好是 NOT 引用数字文字。这可能是由于我对其他DBMS的经验以及避免隐式数据转换引起的问题的需要。我个人的偏好也是使用预准备语句,并避免我的语句包括SQL文本中的文字值。 (对于MySQL而言,这一点大多没有实际意义,因为带有绑定变量的预准备语句在发送到数据库时会转换为纯SQL文本......但这是由MySQL库完成的,而不是我的代码。再次,这是首选是我可能最熟悉的是使用其他RDBMS(Oracle,Teradata,DB2,SQL Server)而不是MySQL本身的长期经验。

答案 1 :(得分:2)

  

使用简单的mysql而不是PDO或其他任何东西

会更专业和防错的方法

我说它是sprintf并且编写可读代码。您通常不希望将变量名称放入字符串中,而是稍后根据顺序添加它们。这使它更加分离并且更容易阅读。

此外,您可以将数值数据指定为%d,以确保它是一个整数值,并且不会出现字符串注入。数字文字通常不需要引号。所以sprintf和SQL在这里合作得很好。 %s需要引号,%d则不需要。然而引用也不会伤害:

$sql_request = "SELECT * 
                  FROM myusers 
                      WHERE user_id = '%d'
                        AND email = '%s' 
                          LIMIT 0,1";

$query = sprintf($sql_request, $user_id, mysql_real_escape_string($email_address, $link));

但是我在你的问题中读到了关于mysqli或PDO的问题。如果可以,请切换到PDO并使用预准备语句/参数化查询。如果这是一个旧的应用程序,请在mysql_*函数前加上一些内容,并根据PDO实现它们自己的功能,然后用新代码缓慢但稳定地替换旧代码。

另外看一下这个问题,它可以帮助你开始移植代码,它的工作相对较快:

关于如何切换到PDO:

答案 2 :(得分:1)

普遍的共识是,将SQL语句编写为插值(您的示例)或连接字符串并不是一个好主意(即,不专业也不防错)。 您应该使用预备语句。

在黑暗时代,我使用了以下功能:

// This is obsolete!!
function escape_input($s) {
  if (!ctype_digit($s))
    return "'" . mysql_real_escape_string($s) . "'";
  else
    return $s;
}

正如您所看到的,我引用了字符串输入,但允许整数输入无需引号即可通过。 (虽然你可以引用整数输入而没有任何不良影响。)我在每个MySQL输入上都使用了这个函数,无论我是否知道输入都是整数。通过强迫自己遵循这种模式,我认为我从未接触过SQL注入攻击。但是,我再也不会这样做了。我会使用PDO或mysqli _ *的预准备语句。

答案 3 :(得分:0)

不应引用User_id列,因为它是数字。但你必须确保传递数值。

答案 4 :(得分:0)

只要确保变量包含数字,您就不需要引用$user_id

如果不是,它可能会破坏您的查询甚至损坏您的数据库!

更好的解决方案是使用PDO或其他库使用预准备语句。

答案 5 :(得分:0)

我强烈建议在引用数值时要小心 - 这就是我发生的事情:经过优化的,经常运行的查询产生了疯狂的IO数量和相当多的CPU负担:

SELECT blah FROM foo WHERE intcolumn='17';

选择性是数百万的约100行。我检查了执行计划:看看驾驶台上的全桌扫描。我一次又一次检查foo(intcolumn)上的索引,甚至丢弃并重新创建它,没有运气。查询时间以分钟为单位。

SELECT blah FROM foo WHERE intcolumn=17;

花了不到0.1秒。出于某种原因,MySQL选择将所有foo.intcolumn强制转换为VARCHAR,然后将字符串与'17'进行比较。当然,这包括忽略指数。

我不知道,如果我在旧版本的MySQL中遇到一个奇怪的bug,我肯定会带走一件事:确保解析器知道我打算使用什么数据类型。使用带引号的数字可能会很棘手。

答案 6 :(得分:-1)

我建议引用。你永远不能太确定! (并且你让MySQL处理可能的错误)。此外,习惯于在变量周围添加引号有助于您记住在习惯它之后总是将它们放在一起并减少错误。 (不要忘记逃避你的输入)

或者,使用预先准备好的语句使用PDO或MySQLi!你甚至不必再引用了。 (是的,对不起。回答一个真正想要使用被弃用的东西的问题让我提供了更好的选择)