Làm thế nào để thoát khỏi chuỗi trong SQL Server bằng cách sử dụng PHP?


85

Tôi đang tìm kiếm giải pháp thay thế mysql_real_escape_string() cho SQL Server. Có phải là addslashes() tùy chọn tốt nhất của tôi hoặc có một chức năng thay thế khác có thể được sử dụng không?

Chỉnh sửa: Phương án thay thế cho mysql_error() cũng sẽ hữu ích.

+2

Đối với tôi nó không phải là một câu hỏi trùng lặp vì nó liên quan đến trường hợp MSSQL cụ thể mà không có một quan chức PDO liên quan 04 mar. 132013-03-04 16:26:42

69

addslashes() không hoàn toàn đầy đủ, nhưng gói mssql của PHP không cung cấp bất kỳ thay thế hợp lý nào. Các giải pháp xấu xí nhưng đầy đủ nói chung được mã hóa các dữ liệu như một bytestring hex, ví dụ:

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

liệu tóm tắt, đó sẽ là:

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() tương đương là mssql_get_last_message().

  0

Bạn có biết tương đương với mysql_insert_id() bởi bất kỳ cơ hội nào không? 22 feb. 092009-02-22 12:20:40

  0

Vâng, bạn thực hiện lệnh SELECT @@ IDENTITY. 22 feb. 092009-02-22 12:24:31

  0

Hỗn loạn, bạn có thể vui lòng cho ví dụ về chức năng 'thoát' sẽ lấy chuỗi làm đối số và trả về thay thế hex do sử dụng phương pháp bạn đã cung cấp không? Tôi sẽ chấp nhận câu trả lời của bạn sau đó 22 feb. 092009-02-22 12:26:45

  0

Hiện tại tôi không chắc chắn về yêu cầu double/quote cho các giá trị hex và cách các giá trị số sẽ được xử lý bằng phương thức này. Một ví dụ về việc sử dụng hàm để thoát khỏi một giá trị và đặt nó vào một truy vấn sẽ là lý tưởng. Cảm ơn trước 22 feb. 092009-02-22 12:27:45

  0

Hy vọng rõ ràng hơn bây giờ ... 22 feb. 092009-02-22 12:31:12

  0

1 câu hỏi, giá trị không cần phải được kèm theo dấu ngoặc kép? Ngoài ra ... có bạn thực hiện bất kỳ thử nghiệm về cách làm việc này với tất cả các loại mã hóa ký tự vv? 22 feb. 092009-02-22 12:33:22

  0

Không. Đó là một chuỗi chữ hex; nếu bạn đính kèm nó trong dấu ngoặc kép, bạn sẽ chèn chuỗi '0xf00ba44' hoặc bất kỳ thứ gì vào cơ sở dữ liệu của bạn thay vì dữ liệu gốc. Tôi đã không thử nghiệm nó với mã hóa khác nhau và tôi đề nghị bất cứ ai sử dụng mã này làm như vậy trước khi làm bất cứ điều gì quan trọng với nó. 22 feb. 092009-02-22 12:37:01

  0

Bạn nên sử dụng SELECT IDENTITY_SCOPE(); từ trong cùng một kết nối của bạn để truy xuất trường ID của bạn thay vì @@ IDENTITY - nó đáng tin cậy hơn. 02 mar. 092009-03-02 19:47:02

+1

Rất tiếc, CHỌN SCOPE_IDENTITY() của nó! 02 mar. 092009-03-02 19:47:37

  0

Chức năng không phù hợp với những gì anh ta hỏi. 26 mar. 102010-03-26 21:00:40

+4

@genio: Mmm, tuyệt vời, ngoại trừ nó thực sự là. Tôi không cho rằng bạn sẽ giải thích những gì bạn cho là vấn đề? 28 mar. 102010-03-28 01:50:57

  0

@chaos Tôi đến muộn với bữa tiệc, nhưng tôi nghĩ Genio là ấn tượng mà anh ta muốn tách các nhân vật nguy hiểm, như vậy là giải pháp của anh ấy. Tôi nghĩ rằng bạn phù hợp với những gì mysql_real_escape_string làm tốt hơn (ít nhất là tôi hiểu nó) 10 nov. 112011-11-10 14:58:12

  0

@chaos Nên làm việc này với tất cả các phiên bản SQL Server? Tôi đang sử dụng SQL Server 2005 (Microsoft SQL Server Management Studio Express 9.00.2047.00) và nó không có vẻ là làm việc. 31 jan. 122012-01-31 11:34:53

  0

@Nalum: Tôi không biết chắc chắn, nhưng cú pháp chữ hexstring chỉ là một điều thú vị mà giải pháp này đang sử dụng, và nó đến từ SQL chuẩn, vì vậy tôi nghĩ họ sẽ triển khai khá sớm. Hãy thử làm như 'SELECT 0x6869' hoặc một cái gì đó để xem khái niệm bsaic có hiệu quả không, tôi đoán vậy. 01 feb. 122012-02-01 03:35:16

  0

@chaos Cảm ơn bạn đã phản hồi, nó không hoạt động, tôi chỉ lấy lại chữ cái hexstring. Tuy nhiên, hãy nhớ điều này. 01 feb. 122012-02-01 11:54:58

  0

@Nalum: Cách duy nhất có ý nghĩa là nếu bạn đang đặt dấu ngoặc kép xung quanh nó. Đó là trường hợp? 01 feb. 122012-02-01 14:20:06

  0

@chaos Không, tôi đã sao chép và dán 'SELECT 0x6869' vào mã và cũng trong SQL Server Management Studio Express và có cùng kết quả trong cả hai. Vì vậy, trừ khi có một số thiết lập trong SQL Server mà không cho phép nó tôi không biết tại sao nó không hoạt động như bạn mô tả. 01 feb. 122012-02-01 16:42:33

  0

@Nalum: Hóa ra đó chỉ là GUI outmarting chính nó. Nó thực sự bảo quản định dạng đặc tả ban đầu của bạn thông qua truy vấn. Tạo một bảng Foo với một cột nvarchar trong đó và 'INSERT INTO Foo VALUES (0x6869)', sau đó 'SELECT * FROM Foo' và bạn sẽ thấy các kết quả khác nhau. 01 feb. 122012-02-01 18:37:31

  0

@chaos Cảm ơn tất cả sự giúp đỡ của bạn về điều này. Khi tôi làm điều đó tôi nhận được một nhân vật hộp mà tôi đoán là để làm với mã hóa ký tự. Tôi không có bất kỳ sự kiểm soát nào đối với cơ sở dữ liệu, vì vậy đừng nghĩ rằng có bất cứ điều gì tôi có thể làm về điều đó.Một lần nữa cảm ơn sự giúp đỡ của bạn :) 03 feb. 122012-02-03 12:49:07

+2

Bạn đã thử điều này với các cột datetime? Tôi nhận được lỗi này: 'SQLSTATE [22007]: Định dạng ngày giờ không hợp lệ: 210 [Microsoft] [ODBC SQL Server Driver] [SQL Server] Chuyển đổi không thành công khi chuyển đổi datetime từ chuỗi nhị phân/varbinary.' Tôi tin rằng phương pháp này có thể đúng chỉ khi nó hoạt động với mọi kiểu dữ liệu MSSQL. 19 jun. 122012-06-19 17:38:41

+1

Nội dung của hàm 'mssql_escape()' trả về không làm việc đó cho tôi. Hiển thị văn bản sau khi thực hiện lựa chọn giống như thế này là '0x4a2761696d65206269656e206c652063686f636f6c6174' do đó không đọc được. 14 aug. 122012-08-14 18:09:47

  0

tính năng này không hoạt động cho các loại định dạng ngày, giờ hoặc định dạng văn bản. Bất kỳ ý tưởng về cách thêm các mục này vào funciton này? Tôi có một công việc aroudn fro ngày và datetime nhưng không có ý tưởng làm thế nào để làm văn bản. 18 sep. 142014-09-18 16:42:09

+3

@JeffNoel Bạn có thể gói các dấu nháy đơn hoặc dấu ngoặc kép. Kể từ khi mục được thoát ra thành hex các dấu ngoặc kép không phải là không cần thiết. SQL Server là nghĩa vụ phải chuyển đổi giá trị hex thành một thứ mà db hiểu được. 18 sep. 142014-09-18 16:44:19

  0

Tôi nghĩ rằng ví dụ tốt hơn là 'SELECT cast (0x6869 như varchar (2)) như SayHI' 21 apr. 162016-04-21 03:02:19

  0

Điều này có thể giúp bạn gặp rắc rối và nó không hoạt động trên tất cả các kiểu dữ liệu. Xem xét sử dụng truy vấn được tham số hóa. Nếu bạn đang tìm cách ngăn chặn việc tiêm SQL, @Konstantin có câu trả lời bảo mật hơn bên dưới. 28 feb. 172017-02-28 22:21:56


10

Bạn có thể xem xét PDO Library. Bạn có thể sử dụng các câu lệnh đã chuẩn bị với PDO, điều này sẽ tự động thoát khỏi bất kỳ ký tự xấu nào trong chuỗi của bạn nếu bạn thực hiện các câu lệnh đã chuẩn bị một cách chính xác. Điều này là dành cho PHP 5 chỉ tôi nghĩ.

  0

Với một số hành vi halfassed Tôi đã nhìn thấy ra khỏi PDO, tôi muốn phải làm một số thử nghiệm nghiêm trọng trước khi tôi tin tưởng nó để thoát khỏi tất cả dữ liệu một cách chính xác. 22 feb. 092009-02-22 12:11:36

  0

@Chaos Thật sao? Tôi không biết điều này .. bạn có liên kết đến một bài báo không? 22 feb. 092009-02-22 12:14:57

  0

Điều tôi đang nghĩ đến là rắc rối mà anh chàng này gặp phải ngày hôm qua là có ngày hôm qua với PDO. Giao dịch không liên quan, nhưng không ấn tượng. Kết hợp với tất cả lịch sử của dữ liệu không đầy đủ thoát trong PHP (php.net nói với mọi người sử dụng addslashes()!) Và tôi nhận được rất đáng ngờ. 22 feb. 092009-02-22 12:22:34

  0

Hmmm .. hy vọng họ có được phần thoát đúng. 22 feb. 092009-02-22 12:33:26

+2

Tôi yêu PDO và cố gắng đầu tiên, nhưng một cho MSSQL (trên Unix, dựa trên dblib) đôi khi thất bại trên tôi (lỗi phân đoạn), đó là lý do tại sao tôi phải dùng đến mssql_escape được định nghĩa ở trên. 06 sep. 112011-09-06 20:58:44

  0

Cảm ơn bạn đã bình luận, @Iapo. Tôi đang cân nhắc việc chuyển sang PDO cho một dự án mssql - đặc biệt để thoát ra - nhưng bạn đã cứu tôi khỏi rắc rối. 24 jul. 132013-07-24 02:34:31


-2

Bạn có thể cuộn phiên bản của riêng mình mysql_real_escape_string, (và cải tiến khi nó) với cụm từ thông dụng sau: [\000\010\011\012\015\032\042\047\134\140]. Điều đó sẽ chăm sóc các ký tự sau: null, backspace, tab ngang, dòng mới, vận chuyển trở lại, thay thế, trích dẫn kép, trích dẫn đơn, dấu gạch chéo ngược, dấu trọng âm. Backspace và tab ngang không được hỗ trợ bởi mysql_real_escape_string.

  0

-1 Lăn của riêng bạn hiếm khi là câu trả lời đúng. 17 jun. 122012-06-17 07:15:18


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

Một số mã ở đây đã bị tách khỏi CodeIgniter. Hoạt động tốt và là một giải pháp sạch.

+1

Đã xác nhận làm việc !! Cảm ơn người đàn ông! 26 mar. 102010-03-26 21:03:03

+1

Tại sao bạn cần 'preg_replace'? Không phải là 'str_replace' đủ? 26 mar. 102010-03-26 21:05:37

  0

gabe: Các preg_replace trong trường hợp này là để cho phép tôi sử dụng các phạm vi dành cho tôi trong các lớp nhân vật biểu thức thông thường. Sẽ có nhiều chuỗi hơn thay thế trong cái này nếu không. 26 mar. 102010-03-26 21:07:16

+6

-1. Nó không phải là trách nhiệm của một hàm trích dẫn đối với dữ liệu mangle - tất cả những gì cần làm là đảm bảo chuỗi ở định dạng như vậy mà nó có thể được thêm vào một câu lệnh SQL và tồn tại chưa sửa đổi. 15 jul. 102010-07-15 06:38:48

+6

Xin lỗi, nhưng điều này sai từ dòng đầu tiên của mã - 'rỗng ($ value)' sẽ trả về 'true' không chỉ cho' '' ', mà còn cho' null', '0' và' '0'' ! Bạn sẽ trả về một chuỗi rỗng trong tất cả các trường hợp đó. 25 dec. 102010-12-25 13:45:40

  0

Tôi upvoted này, tôi nghĩ rằng đó là một chức năng hoàn toàn tốt miễn là bạn hoàn toàn nhận thức được các vấn đề trên. Tôi sẽ gọi nó là ms_escape_and_strip_string, vì vậy bất kỳ ai khác làm việc trên nó sẽ thấy nó thực hiện cả hai nhiệm vụ đó. Có một chuỗi rỗng được trả lại trong nhiều trường hợp là tốt miễn là bạn chiếm nó, trừ khi tôi chỉ thiếu một điểm lớn hơn ở đây. Nếu điều này không phù hợp với nhu cầu của bạn, bạn luôn có thể lấy dòng đó ra và thay thế nó bằng logic phù hợp với nhu cầu của bạn. 10 nov. 112011-11-10 14:40:14

  0

Điều này không bao gồm tất cả các mã url như không gian =% 20. 30 mar. 162016-03-30 11:32:39


1

tôi biết, hơi muộn một chút, nhưng câu trả lời từ 'Feb 22 '09 at 12:10' bởi sự hỗn loạn isn`t phù hợp với tất cả các truy vấn. Ví dụ: "TẠO ĐĂNG NHẬP [0x6f6c6f6c6f] TỪ WINDOWS" sẽ cho bạn ngoại lệ

p.s. nhìn vào trình điều khiển mssql cho php, http://msdn.microsoft.com/library/cc296181%28v=sql.90%29.aspx và sqlsrv_prepare chức năng, mà có thể ràng buộc params.

p.s.s. mà cũng không giúp bạn với truy vấn ở trên;)


2

Sau khi đấu tranh với điều này trong nhiều giờ, tôi đã đưa ra một giải pháp mà cảm thấy gần như tốt nhất.

Câu trả lời của Chaos về các giá trị chuyển đổi thành chuỗi thập phân không hoạt động với mọi kiểu dữ liệu, cụ thể với các cột datetime.

Tôi sử dụng PHP PDO::quote(), nhưng khi đi kèm với PHP, PDO::quote() không được hỗ trợ cho MS SQL Server và trả về FALSE. Giải pháp để nó hoạt động là tải xuống một số gói Microsoft:

Sau đó bạn có thể kết nối trong PHP với PDO sử dụng một DSN như ví dụ sau:

sqlsrv:Server=192.168.0.25; Database=My_Database; 

Sử dụng các thông số UIDPWD trong DSN không làm việc, vì vậy tên truy cập và mật khẩu được thông qua làm tham số thứ hai và thứ ba trên hàm tạo PDO khi tạo kết nối. Bây giờ bạn có thể sử dụng PDO::quote() của PHP. Thưởng thức.


2

Để thoát khỏi đơn và hai dấu ngoặc kép, bạn phải tăng gấp đôi chúng lên:

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

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

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

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

vv ...

và phân bổ: Escape Character In Microsoft SQL Server 2000


5

một cách khác để xử lý dấu nháy đơn và kép là

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

câu trả lời tuyệt vời và cảm ơn 19 jan. 162016-01-19 12:46:33

  0

get_magic_quites_gpc đã được DEPRECATED là của PHP 5.3.0 và REMOVED là của PHP 5.4.0. Xem http://php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc 19 jan. 182018-01-19 14:09:15


9

Tại sao bạn bận tâm thoát khỏi bất cứ điều gì khi bạn có thể sử dụng các tham số trong truy vấn của mình ?!

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

Nó hoạt động ngay trong các lựa chọn, xóa, cập nhật bất kể thông số giá trị của bạn là null hay không. Thực hiện một nguyên tắc - Không nối SQL và bạn luôn an toàn và các truy vấn của bạn đọc tốt hơn nhiều.

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

  0

Đây là phương pháp chính xác. Bạn nên luôn sử dụng các tham số trái với các truy vấn đặc biệt. Tuy nhiên, OP không sử dụng các trình điều khiển sqlsrv. Anh ta đang sử dụng các trình điều khiển mssql. do đó liên kết để sử dụng cho những người bạn bị kẹt sử dụng trình điều khiển sqlsrv là [http://php.net/manual/en/function.mssql-query.php](http://php.net/manual/en/function. mssql-query.php). 28 feb. 172017-02-28 22:19:43

+1

@ smulholland2 Ý của bạn là "hoặc những người bạn bị kẹt sử dụng trình điều khiển _MSSQL_" 01 mar. 172017-03-01 09:51:38


0

Warning: This function was REMOVED in PHP 7.0.0.

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

Đối với bất cứ ai vẫn còn sử dụng những mssql_ * chức năng, hãy ghi nhớ rằng họ đã được gỡ bỏ từ PHP như của phiên bản 7.0.0. Vì vậy, điều đó có nghĩa là bạn cuối cùng phải viết lại mã mô hình của bạn để sử dụng thư viện PDO, sqlsrv_ * vv. Nếu bạn đang tìm kiếm một phương thức "trích dẫn/thoát", tôi sẽ giới thiệu PDO.

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


-1

Đối với việc chuyển đổi để có được những HEX trong SQL trở thành ASCII đây là giải pháp tôi có về vấn đề này (bằng cách sử dụng chức năng từ Chaos để mã hóa vào Hex)

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

Nếu bạn đang sử dụng PDO , bạn có thể sử dụng phương thức PDO::quote.


-1

tôi đã được sử dụng điều này như một sự thay thế của 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)); 

0

Không phải là nó tốt hơn cũng để thoát khỏi từ dành riêng SQL?Ví dụ:

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