[php] How to escape strings in SQL Server using PHP?

I'm looking for the alternative of mysql_real_escape_string() for SQL Server. Is addslashes() my best option or there is another alternative function that can be used?

An alternative for mysql_error() would also be useful.

This question is related to php sql-server escaping input-sanitization

The answer is


Why would you bother escaping anything when you can use parameters in your query?!

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

It works right in selects, deletes, updates regardless whether your values parameters are null or not. Make a matter of principle - Don't concatenate SQL and you are always safe and your queries read much better.

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


You could look into the PDO Library. You can use prepared statements with PDO, which will automatically escape any bad characters in your strings if you do the prepared statements correctly. This is for PHP 5 only I think.


After struggling with this for hours, I've come up with a solution that feels almost the best.

Chaos' answer of converting values to hexstring doesn't work with every datatype, specifically with datetime columns.

I use PHP's PDO::quote(), but as it comes with PHP, PDO::quote() is not supported for MS SQL Server and returns FALSE. The solution for it to work was to download some Microsoft bundles:

After that you can connect in PHP with PDO using a DSN like the following example:

sqlsrv:Server=192.168.0.25; Database=My_Database;

Using the UID and PWD parameters in the DSN didn't worked, so username and password are passed as the second and third parameters on the PDO constructor when creating the connection. Now you can use PHP's PDO::quote(). Enjoy.


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

Some of the code here was ripped off from CodeIgniter. Works well and is a clean solution.

EDIT: There are plenty of issues with that code snippet above. Please don't use this without reading the comments to know what those are. Better yet, please don't use this at all. Parameterized queries are your friends: http://php.net/manual/en/pdo.prepared-statements.php


An answer from 2009-02-22T121000 by user chaos doesn't fit all queries.

For example, "CREATE LOGIN [0x6f6c6f6c6f] FROM WINDOWS" will give you an exception.

PS: look at the SQL Server driver for PHP, http://msdn.microsoft.com/library/cc296181%28v=sql.90%29.aspx and the sqlsrv_prepare function, which can binds parameters.

PSS: Which also didn't help you with the query above ;)


In order to escape single- and double-quotes, you have to double them up:

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

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

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

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

etc...

and attribution: Escape Character In Microsoft SQL Server 2000


You could roll your own version of mysql_real_escape_string, (and improve upon it) with the following regular expression: [\000\010\011\012\015\032\042\047\134\140]. That takes care of the following characters: null, backspace, horizontal tab, new line, carriage return, substitute, double quote, single quote, backslash, grave accent. Backspace and horizontal tab are not supported by mysql_real_escape_string.


It is better to also escape SQL reserved words. For example:

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

Warning: This function was REMOVED in PHP 7.0.0.

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

For anyone still using these mssql_* functions, keep in mind that they have been removed from PHP as of v7.0.0. So, that means you eventually have to rewrite your model code to either use the PDO library, sqlsrv_* etc. If you're looking for something with a "quoting/escaping" method, I would recommend PDO.

Alternatives to this function include: PDO::query(), sqlsrv_query() and odbc_exec()


I have been using this as an alternative of mysql_real_escape_string():

function htmlsan($htmlsanitize){
    return $htmlsanitize = htmlspecialchars($htmlsanitize, ENT_QUOTES, 'UTF-8');
}
$data = "Whatever the value's is";
$data = stripslashes(htmlsan($data));

For the conversion to get the hexadecimal values in SQL back into ASCII, here is the solution I got on this (using the function from user chaos to encode into hexadecimal)

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

function hexDecode($hex) {
    $str = '';
    for ($i=0; $i<strlen($hex); $i += 2)
        $str .= chr(hexdec(substr($hex, $i, 2)));
    return $str;
}

$stringHex = hexEncode('Test String');
var_dump($stringHex);
$stringAscii = hexDecode($stringHex);
var_dump($stringAscii);

Another way to handle single and double quotes is:

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

If you are using PDO, you can use the PDO::quote method.


Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to sql-server

Passing multiple values for same variable in stored procedure SQL permissions for roles Count the Number of Tables in a SQL Server Database Visual Studio 2017 does not have Business Intelligence Integration Services/Projects ALTER TABLE DROP COLUMN failed because one or more objects access this column Create Local SQL Server database How to create temp table using Create statement in SQL Server? SQL Query Where Date = Today Minus 7 Days How do I pass a list as a parameter in a stored procedure? SQL Server date format yyyymmdd

Examples related to escaping

Uses for the '&quot;' entity in HTML Javascript - How to show escape characters in a string? How to print a single backslash? How to escape special characters of a string with single backslashes Saving utf-8 texts with json.dumps as UTF8, not as \u escape sequence Properly escape a double quote in CSV How to Git stash pop specific stash in 1.8.3? In Java, should I escape a single quotation mark (') in String (double quoted)? How do I escape a single quote ( ' ) in JavaScript? Which characters need to be escaped when using Bash?

Examples related to input-sanitization

How to escape strings in SQL Server using PHP?