如何使用PHP在SQL Server中转义字符串?

Cli*_*ote 88 php sql-server escaping input-sanitization

我正在寻找mysql_real_escape_string()SQL Server 的替代方案.是addslashes()我最好的选择还是可以使用另一种替代功能?

编辑:替代品mysql_error()也很有用.

cha*_*aos 73

addslashes()不完全足够,但PHP的mssql包没有提供任何体面的选择.丑陋但完全通用的解决方案是将数据编码为十六进制字节串,即

$unpacked = unpack('H*hex', $data);
mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (0x' . $unpacked['hex'] . ')
');
Run Code Online (Sandbox Code Playgroud)

抽象,那将是:

function mssql_escape($data) {
    if(is_numeric($data))
        return $data;
    $unpacked = unpack('H*hex', $data);
    return '0x' . $unpacked['hex'];
}

mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (' . mssql_escape($somevalue) . ')
');
Run Code Online (Sandbox Code Playgroud)

mysql_error()相当于mssql_get_last_message().

  • @genio:嗯,很棒,除了它实际上是.我不认为你会解释你认为是什么问题? (4认同)
  • 你用datetime列试过这个吗?我收到此错误:`SQLSTATE [22007]:无效的日期时间格式:210 [Microsoft] [ODBC SQL Server驱动程序] [SQL Server]从二进制/ varbinary字符串转换datetime时转换失败.我相信这种方法可以正确只有它适用于每个MSSQL数据类型. (3认同)
  • @JeffNoel您可能包装字符串单引号或双引号.由于该项目已转义为十六进制,因此引号不是必需的.SQL Server应该将十六进制值转换为db理解的内容. (3认同)

gen*_*nio 40

function ms_escape_string($data) {
        if ( !isset($data) or empty($data) ) return '';
        if ( is_numeric($data) ) return $data;

        $non_displayables = array(
            '/%0[0-8bcef]/',            // url encoded 00-08, 11, 12, 14, 15
            '/%1[0-9a-f]/',             // url encoded 16-31
            '/[\x00-\x08]/',            // 00-08
            '/\x0b/',                   // 11
            '/\x0c/',                   // 12
            '/[\x0e-\x1f]/'             // 14-31
        );
        foreach ( $non_displayables as $regex )
            $data = preg_replace( $regex, '', $data );
        $data = str_replace("'", "''", $data );
        return $data;
    }
Run Code Online (Sandbox Code Playgroud)

这里的一些代码是从CodeIgniter中删除的.效果很好,是一个干净的解决方案.

编辑:上面的代码片段有很多问题.请不要在没有阅读评论的情况下使用它来了解它们是什么.更好的是,请不要使用它.参数化查询是您的朋友:http://php.net/manual/en/pdo.prepared-statements.php

  • -1.引用函数不应该破坏数据 - 它应该做的就是确保字符串的格式可以添加到SQL语句中并且不受修改. (7认同)
  • 对不起,但是从第一行代码开始这是错误的 - "empty($ value)"将返回`true`,不仅仅是'''',还有`null`,`0`和''0'!在所有这些情况下,您将返回一个空字符串. (6认同)
  • 我对此表示赞同,我认为只要您充分意识到上述问题,这就是一个非常好的功能。不过,我将其称为 ms_escape_and_strip_string,因此其他处理它的人都会看到它执行这两项任务。只要您考虑到它,在多种情况下返回空字符串就可以了,除非我在这里错过了更重要的一点。如果这不符合您的需求,您可以随时删除该行并用适合您需求的逻辑替换它。 (2认同)

Kon*_*tin 15

当你可以在查询中使用参数时,为什么还要麻烦逃避任何事情?!

sqlsrv_query(
    $connection, 
    'UPDATE some_table SET some_field = ? WHERE other_field = ?', 
    array($_REQUEST['some_field'], $_REQUEST['id'])
)
Run Code Online (Sandbox Code Playgroud)

无论您的值参数是否合适,它都可以在选择,删除,更新中null正常工作.原则问题 - 不要连接SQL,你总是安全的,你的查询读得更好.

http://php.net/manual/en/function.sqlsrv-query.php

  • @smulholland2 你的意思是“或者你们中的那些人一直在使用 _MSSQL_ 驱动程序” (2认同)

ale*_*lex 10

您可以查看PDO库.您可以将预准备语句与PDO一起使用,如果您正确执行预准备语句,它将自动转义字符串中的任何错误字符.这只适用于PHP 5,我认为.

  • 我喜欢PDO并且首先尝试过,但MSSQL(在Unix上,基于dblib)有时会失败(分段错误),这就是我使用上面定义的mssql_escape的原因. (2认同)

小智 5

另一种处理单引号和双引号的方法是

function mssql_escape($str)
{
    if(get_magic_quotes_gpc())
    {
        $str = stripslashes($str);
    }
    return str_replace("'", "''", $str);
}
Run Code Online (Sandbox Code Playgroud)