PHP를 사용하여 SQL Server에서 문자열을 이스케이프하는 방법은 무엇입니까?


89

mysql_real_escape_string()SQL Server 의 대안을 찾고 있습니다. 가 addslashes()내 최선의 선택은 또는 사용할 수있는 또 다른 기능은 무엇입니까?

에 대한 대안 mysql_error()도 유용합니다.


2
이 관련 공식 PDO가없는 특정의 MSSQL의 경우 우려 때문에 나에게는 중복 질문이 아니다
피에르 드 LESPINAY

답변:


74

addslashes()완전히 적절하지는 않지만 PHP의 mssql 패키지는 적절한 대안을 제공하지 않습니다. 추악하지만 완전히 일반적인 솔루션은 데이터를 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()입니다.


1
죄송합니다. SELECT SCOPE_IDENTITY ()!
Bryan Rehbein

4
@genio : 음, 대단하지만 실제로는 그렇지 않습니다. 문제라고 생각하는 것을 설명하지 않겠습니까?
chaos

3
datetime 열로 이것을 시도해 보셨습니까? 이 오류가 발생합니다. SQLSTATE[22007]: Invalid datetime format: 210 [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting datetime from binary/varbinary string.모든 MSSQL 데이터 유형에서 작동하는 경우에만이 방법이 올바르다 고 생각합니다.
Alejandro García Iglesias

1
mssql_escape()반환 된 함수 의 내용이 나를 위해하지 않습니다. 선택을 한 후 텍스트 디스플레이가 이렇게 보이기 0x4a2761696d65206269656e206c652063686f636f6c6174때문에 읽을 수 없습니다.
Jeff Noel

3
@JeffNoel 아마도 문자열 작은 따옴표 또는 큰 따옴표를 래핑합니다. 항목이 16 진수로 이스케이프되므로 따옴표가 필요하지 않습니다. SQL Server는 16 진수 값을 db가 이해하는 값으로 변환해야합니다.
danielson317

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

여기에있는 코드 중 일부는 CodeIgniter에서 추출되었습니다. 잘 작동하고 깨끗한 솔루션입니다.

편집 : 위의 코드 조각에는 많은 문제가 있습니다. 그것이 무엇인지 알기 위해 주석을 읽지 않고 이것을 사용하지 마십시오. 더 나은 방법은 이것을 전혀 사용하지 마십시오. 매개 변수화 된 쿼리는 친구입니다 : http://php.net/manual/en/pdo.prepared-statements.php


1
왜 필요 preg_replace합니까? str_replace충분 하지 않습니까?
Gabe

gabe :이 경우 preg_replace는 정규식 문자 클래스에서 내게 제공되는 범위를 사용할 수 있도록하는 것입니다. 그렇지 않으면 더 많은 문자열 대체가있을 것입니다.
genio

7
-1. 데이터를 엉망으로 만드는 것은 인용 함수의 책임이 아닙니다. 문자열이 SQL 문에 추가되고 수정되지 않은 상태로 유지 될 수있는 형식인지 확인하기 만하면됩니다.
차오

6
- 죄송하지만이 코드의 첫 번째 줄에서 잘못 empty($value)반환 true뿐만 아니라위한 ''뿐만 아니라위한 null, 0'0'! 이러한 모든 경우에 빈 문자열을 반환합니다.
Nux

나는 이것을 upvoted, 나는 당신이 위의 문제를 완전히 알고있는 한 완벽하게 훌륭한 기능이라고 생각합니다. 나는 그것을 ms_escape_and_strip_string이라고 부를 것이므로 다른 사람이 작업을 수행하는 것을 볼 수 있습니다. 여기에서 더 큰 요점을 놓치고 있지 않는 한 여러 경우에 빈 문자열을 반환하는 것이 좋습니다. 이것이 당신의 필요에 맞지 않는다면 당신은 항상 그 라인을 꺼내 당신의 필요에 맞는 로직으로 대체 할 수 있습니다.
NateDSaint

16

쿼리에서 매개 변수를 사용할 수 있는데 왜 이스케이프 처리를해야합니까?!

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


이것이 올바른 접근 방식입니다. 임시 쿼리와는 반대로 항상 매개 변수를 사용해야합니다. 그러나 OP는 sqlsrv 드라이버를 사용하지 않습니다. 그는 mssql 드라이버를 사용하고 있습니다. 따라서 sqlsrv 드라이버를 사용하는 사람들을 위해 사용할 링크는 http://php.net/manual/en/function.mssql-query.php 입니다.
smulholland2

1
@ smulholland2는 찾으 셨나요? "또는 당신의 그들을 사용하여 붙어 MSSQL의 드라이버를"
콘스탄틴

한 가지 시나리오는 데이터 마이그레이션 시나리오에서 사용할 INSERT 문의 파일을 생성하려는 경우 일 수 있습니다.
Gary Reckard

11

PDO 라이브러리를 살펴볼 수 있습니다 . 준비된 명령문을 올바르게 수행하면 문자열에서 잘못된 문자를 자동으로 이스케이프하는 PDO와 함께 준비된 명령문을 사용할 수 있습니다. 이것은 PHP 5 전용이라고 생각합니다.


내가 PDO에서 본 절반 정도의 행동으로 모든 데이터를 올바르게 이스케이프하기 위해 신뢰하기 전에 몇 가지 심각한 테스트를 수행해야했습니다.
chaos

@Chaos 정말? 잘 모르겠네요 .. 기사 링크가 있나요?
alex

내가 생각한 것은이 사람이 어제 PDO에서 겪었던 문제였습니다. 관련없는 거래 항목이지만 인상적이지 않습니다. PHP에서 불충분 한 데이터 이스케이프 기록 (php.net이 사람들에게 addlash ()을 사용하라고 말함!)과 결합하면 매우 의심스러워집니다.
chaos

2
나는 PDO를 좋아하고 먼저 시도했지만 MSSQL (dblib 기반 Unix)에서 가끔 실패 (분할 오류)가 발생했기 때문에 위에서 정의한 mssql_escape를 사용했습니다.
lapo 2011 년

귀하의 의견에 감사드립니다, @Iapo. 나는 특히 탈출하기 위해 mssql 프로젝트를 위해 PDO로 전환하는 것을 고려하고 있었지만 문제를 해결했습니다.
Winfield Trail


2

작은 따옴표와 큰 따옴표를 이스케이프하려면 두 배로 늘려야합니다.

$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

몇 시간 동안 고생 한 끝에 거의 가장 기분이 좋은 솔루션을 찾았습니다.

값을 hexstring으로 변환하는 Chaos의 대답은 모든 데이터 유형, 특히 datetime 열에서 작동하지 않습니다.

PHP를 사용 PDO::quote()하지만 PHP와 함께 제공되므로 PDO::quote()MS SQL Server에서 지원되지 않으며 FALSE. 작동하는 솔루션은 일부 Microsoft 번들을 다운로드하는 것입니다.

그런 다음 다음 예제와 같이 DSN을 사용하여 PDO와 PHP에서 연결할 수 있습니다.

sqlsrv:Server=192.168.0.25; Database=My_Database;

DSN에서 UIDPWD매개 변수를 사용하는 것이 작동하지 않았으므로 연결을 만들 때 PDO 생성자에서 두 번째 및 세 번째 매개 변수로 사용자 이름과 암호가 전달됩니다. 이제 PHP의 PDO::quote(). 즐겨.



0

경고 :이 함수는 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

SQL의 16 진수 값을 ASCII로 다시 가져 오는 변환을 위해 여기에 제가 얻은 솔루션이 있습니다 ( 사용자 혼돈 의 함수 를 사용하여 16 진수로 인코딩).

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

0

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

-1

나는 이것을 대안으로 사용하고 있습니다 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));

-2

mysql_real_escape_string다음 정규식을 사용 하여 자신의 버전을 롤링 (및 개선) 할 수 [\000\010\011\012\015\032\042\047\134\140]있습니다.. 다음 문자를 처리합니다 : null, 백 스페이스, 가로 탭, 새 줄, 캐리지 리턴, 대체, 큰 따옴표, 작은 따옴표, 백 슬래시, 억음 악센트. 백 스페이스 및 가로 탭은에서 지원되지 않습니다 mysql_real_escape_string.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.