web-dev-qa-db-ja.com

PHPを使用してSQL Serverで文字列をエスケープする方法は?

SQL Serverのmysql_real_escape_string()の代替を探しています。 addslashes()は私の最良の選択肢ですか、または使用できる別の代替関数がありますか?

mysql_error()の代替も有用です。

87
Click Upvote

addslashes()は完全に適切ではありませんが、PHPのmssqlパッケージは適切な代替手段を提供しません。 ugいが完全に一般的な解決策は、データを16進バイト文字列としてエンコードすることです。

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

抽象化すると、次のようになります。

_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) . ')
');
_

mysql_error()に相当するのはmssql_get_last_message()です。

72
chaos
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;
    }

ここのコードの一部は、CodeIgniterからはぎ取られました。うまく機能し、クリーンなソリューションです。

編集:上記のコードスニペットには多くの問題があります。コメントを読んでそれらが何であるかを知ることなくこれを使用しないでください。さらに良いことに、これをまったく使用しないでください。パラメータ化されたクエリは友達です: http://php.net/manual/en/pdo.prepared-statements.php

40
genio

クエリでパラメータを使用できるのに、なぜわざわざエスケープするのですか?!

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

値パラメーターがnullであるかどうかに関係なく、選択、削除、更新で正しく機能します。原則を確認してください-SQLを連結しないでください。常に安全であり、クエリの読みやすさが向上します。

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

15
Konstantin

PDO Library を調べることができます。 PDOでプリペアドステートメントを使用できます。PDOは、プリペアドステートメントを正しく実行すると、文字列内の不良文字を自動的にエスケープします。これはPHP 5のみだと思います。

10
alex

一重引用符と二重引用符を処理する別の方法は次のとおりです。

function mssql_escape($str)
{
    if(get_magic_quotes_gpc())
    {
        $str = stripslashes($str);
    }
    return str_replace("'", "''", $str);
}
4

これに何時間も苦労した後、私はほとんど最高の気分になるソリューションを思いつきました。

値を16進文字列に変換するというカオスの答えは、すべてのデータ型、特に日時列では機能しません。

PHPのPDO::quote()を使用していますが、PHPに付属しているため、PDO::quote()はMS SQL Serverでサポートされておらず、FALSEを返します。動作するためのソリューションは、いくつかのMicrosoftバンドルをダウンロードすることでした:

  • Microsoft Drivers 3.0 for PHP for SQL Server (SQLSRV30.EXE):ダウンロードし、指示に従ってインストールします。
  • Microsoft®SQLServer®2012 Native Client :Native Clientの広範なページを検索します。 2012年であっても、SQL Server 2008への接続に使用しています(2008 Native Clientのインストールは機能しませんでした)。ダウンロードしてインストールします。

その後、次の例のようにDSNを使用してPDOでPHPに接続できます。

_sqlsrv:Server=192.168.0.25; Database=My_Database;
_

DSNでUIDおよびPWDパラメーターを使用しても機能しなかったため、接続の作成時にPDOコンストラクターの2番目と3番目のパラメーターとしてユーザー名とパスワードが渡されます。これで、PHPのPDO::quote()を使用できます。楽しい。

一重引用符と二重引用符をエスケープするには、それらを二重にする必要があります。

_$value = 'This is a quote, "I said, 'Hi'"';

$value = str_replace( "'", "''", $value ); 
_

$value = str_replace( '"', '""', $value );

_$query = "INSERT INTO TableName ( TextFieldName ) VALUES ( '$value' ) ";
_

等...

および属性: Microsoft SQL Server 2000のエスケープ文字

2
marklark

ユーザーによる2009-02-22T121000からの回答chaos はすべてのクエリに適合しません。

たとえば、「CREATE LOGIN [0x6f6c6f6c6f] FROM WINDOWS」は例外を提供します。

PS:PHPのSQL Serverドライバー、 http://msdn.Microsoft.com/library/cc296181%28v=sql.90%29.aspx およびパラメーターをバインドできるsqlsrv_prepare関数を見てください。 。

PSS:上記のクエリでも役に立たなかった;)

1
danechkin

PDOを使用している場合は、 PDO::quote メソッド。

0
Fredric Yeung

警告:この関数はPHP 7.0.0。で削除されました。

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

これらのmssql_ *関数をまだ使用している場合、v7.0.0の時点でPHPから削除されていることに注意してください。 PDOライブラリ、sqlsrv_ *など。「引用/エスケープ」メソッドで何かを探しているなら、PDOをお勧めします。

この関数の代替:PDO :: query()、sqlsrv_query()およびodbc_exec()

0
jjwdesign

SQL予約語もエスケープすることをお勧めします。例えば:

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
        '/\27/'
    );
    foreach ($non_displayables as $regex)
        $data = preg_replace( $regex, '', $data);
    $reemplazar = array('"', "'", '=');
    $data = str_replace($reemplazar, "*", $data);
    return $data;
}
0
Alex360