web-dev-qa-db-fra.com

Comment échapper aux chaînes de caractères dans SQL Server en utilisant PHP?

Je cherche l'alternative de mysql_real_escape_string() pour SQL Server. addslashes() est-il ma meilleure option ou existe-t-il une autre fonction alternative pouvant être utilisée?

Edit : Une alternative à mysql_error() serait également utile.

86
Click Upvote

addslashes() n'est pas tout à fait adéquat, mais le paquetage mssql de PHP ne fournit aucune alternative décente. La solution laide mais tout à fait générale consiste à coder les données sous la forme d’une chaîne de bytest hexadécimale, c.-à-d.

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

Résumé, ce serait:

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() équivalent est mssql_get_last_message().

71
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;
    }

Une partie du code ici a été arraché de CodeIgniter. Fonctionne bien et est une solution propre.

EDIT: Il y a beaucoup de problèmes avec cet extrait de code ci-dessus. Ne l'utilisez pas sans lire les commentaires pour savoir ce que c'est. Mieux encore, s'il vous plaît ne l'utilisez pas du tout. Les requêtes paramétrées sont vos amis: http://php.net/manual/en/pdo.prepared-statements.php

40
genio

Pourquoi voudriez-vous déranger quoi que ce soit lorsque vous pouvez utiliser des paramètres dans votre requête?!

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

Cela fonctionne bien dans les sélections, les suppressions et les mises à jour, que vos paramètres de valeur soient null ou non . Faites une question de principe - Ne concaténez pas SQL et vous êtes toujours en sécurité et vos requêtes lues beaucoup mieux. 

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

13
Konstantin

Vous pouvez regarder dans la Bibliothèque PDO . Vous pouvez utiliser des instructions préparées avec PDO, qui échapperont automatiquement à tous les caractères incorrects de vos chaînes si vous les exécutez correctement. Ceci est pour PHP 5 seulement je pense.

10
alex

une autre façon de gérer les guillemets simples et doubles est 

function mssql_escape($str)
{
   if(get_magic_quotes_gpc())
   {
    $str= stripslashes($str);
   }
   return str_replace("'", "''", $str);
}
5
Raja Bilal Ahmed

Après avoir lutté avec cela pendant des heures, j'ai mis au point une solution qui semble presque la meilleure.

La réponse de Chaos consistant à convertir des valeurs en hexstring ne fonctionne pas avec tous les types de données, en particulier avec les colonnes datetime.

J'utilise PDO::quote() de PHP, mais comme il est fourni avec PHP, PDO::quote() n'est pas pris en charge pour MS SQL Server et renvoie FALSE. La solution pour que cela fonctionne consiste à télécharger des bundles Microsoft:

Après cela, vous pouvez vous connecter à PHP avec PDO en utilisant un DSN comme dans l'exemple suivant:

sqlsrv:Server=192.168.0.25; Database=My_Database;

L'utilisation des paramètres UID et PWD dans le DSN n'a pas fonctionné, de sorte que le nom d'utilisateur et le mot de passe sont passés comme deuxième et troisième paramètres du constructeur PDO lors de la création de la connexion . Vous pouvez maintenant utiliser la fonction PDO::quote() de PHP. Prendre plaisir.

Pour échapper aux guillemets simples et doubles, vous devez les doubler:

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

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

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

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

etc...

et attribution: caractère d'échappement dans Microsoft SQL Server 20

2
marklark

je sais que je suis un peu en retard, mais la réponse de '22 février 2009 à 12h10' de chaos n'est pas à la hauteur de toutes les requêtes. E.g: "CREATE LOGIN [0x6f6c6f6c6f] DE WINDOWS" vous donnera une exception

p.s. regardez pilote mssql pour php, http://msdn.Microsoft.com/library/cc296181%28v=sql.90%29.aspx et sqlsrv_prepare, qui peut lier les paramètres.

p.s.s. qui ne vous a pas non plus aidé avec la requête ci-dessus;)

1
danechkin

Si vous utilisez PDO, vous pouvez utiliser la méthode PDO::quote .

0
Fredric Yeung

Avertissement: cette fonction a été supprimée dans PHP 7.0.0.

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

Si vous utilisez toujours ces fonctions mssql_ *, n'oubliez pas qu'elles ont été supprimées de PHP à partir de v7.0.0. Cela signifie donc que vous devrez éventuellement réécrire votre code de modèle pour utiliser la bibliothèque PDO, sqlsrv_ * etc. Si vous recherchez quelque chose avec une méthode "quoting/escaping", je recommanderais PDO.

Les alternatives à cette fonction incluent: PDO :: query (), sqlsrv_query () et odbc_exec ()

0
jjwdesign

Ne vaut-il pas mieux aussi échapper aux mots réservés SQL? Par exemple:

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