我应该如何转义此LIKE查询中的字符?

时间:2011-09-06 22:54:08

标签: mysql escaping sql-like

我的一个表中有一个包含此字符串的字段:

!"#¤%&/()=?´`?=)(/&%¤#"!\'\'"'

(仅用于测试目的)。我已经尝试了无数的查询来正确选择这个字段,当然没有返回任何错误,但我似乎无法做到正确。

这是我目前正在使用的查询:

SELECT * FROM mytable WHERE `column` LIKE '%!"#¤%&/()=?´`?=)(/&%¤#"!\\\'\\\'"\'%'

任何人都可以了解一下我做得对吗?我应该逃避任何其他角色('除外)吗?我还没有在任何地方读过它...(但我尝试在precent符号之前添加反斜杠。)

4 个答案:

答案 0 :(得分:7)

来自MySQL Manual

  

因为MySQL在字符串中使用C转义语法(例如,“\n”来表示换行符),所以必须将在\字符串中使用的任何“LIKE”加倍。例如,要搜索“\n”,请将其指定为“\\n”。要搜索“\”,请将其指定为“\\\\”;这是因为解析器会将反斜杠剥离一次,并且在进行模式匹配时再次剥离反斜杠,只留下一个反斜杠。

因此,您应该分两步为LIKE运算符转义字符串。

在PHP中它可以是这样的:

// Your search string, for example, from POST field
$string = $_POST['column'];

// First step - LIKE escaping
$string = str_replace(array('\\', '_', '%'), array('\\\\', '\\_', '\\%'), $string);

// Second step - literal escaping
$string = mysql_real_escape_string($string);

// Result query
mysql_query("SELECT * FROM `table` WHERE `column` LIKE '%".$string."%'");

<强>更新

  

MySQL 扩展在PHP 5.5.0中已弃用,并且在PHP 7.0.0中已被删除。相反,应使用 MySQLi PDO_MySQL 扩展名。

使用MySQLi

// Connect to database
$mysqli = new mysqli('localhost', 'username', 'password', 'database');

// Your search string, for example, from POST field
$string = $_POST['column'];

// First step - LIKE escaping
$string = str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $string);

// Second step - literal escaping
$string = $mysqli->real_escape_string($string);

// Result query
$mysqli->query("SELECT * FROM `table` WHERE `column` LIKE '%{$string}%'");

使用PDO

// Connect to database
$conn = new PDO('mysql:host=localhost;dbname=database', 'username', 'password');

// Your search string, for example, from POST field
$string = $_POST['column'];

// First step - LIKE escaping
$string = str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $string);

// Second step - literal escaping
$string = $conn->quote($string);

// Result query
$conn->query("SELECT * FROM `table` WHERE `column` LIKE '%{$string}%'");

或者您可以使用 PDO准备好的声明,而不是第二步(文字转义):

// Connect to database
$conn = new PDO('mysql:host=localhost;dbname=database', 'username', 'password');

// Your search string, for example, from POST field
$string = $_POST['column'];

// First step - LIKE escaping
$string = str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $string);

// Prepare a statement for execution
$statement = $conn->prepare("SELECT * FROM `table` WHERE `column` LIKE ?");

// Execute a prepared statement
$statement->execute(["%{$string}%"]);

答案 1 :(得分:2)

不清楚你想要获得什么以及出了什么问题。

顺便说一句,如果你想保护你的查询免受SQL注入,你应该使用mysql_real_escape_string
http://dev.mysql.com/doc/refman/5.0/en/mysql-real-escape-string.html

假设您使用的是PHP

$query = "SELECT * FROM mytable WHERE `column` LIKE '".mysql_real_escape_string($whatever)."'"

但你必须记住LIKE算子有他自己的特殊字符(野人)
http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like

% Matches any number of characters, even zero characters
_ Matches exactly one character

因此,如果您要停止魔法

,则必须使用反斜杠转义此字符

假设您使用PHP,我会这样做

// This removes magic on LIKE wildchars
$whatever = preg_replace('#(%|_)#', '\\$1', $input);

// This secures the query from sql injection 
// and hads the trailing % wildchars to the search string
$query = "SELECT * FROM mytable WHERE `column` LIKE '%".mysql_real_escape_string($whatever)."%'"

答案 2 :(得分:0)

您使用的是PHP吗?如果是这样,您可以尝试类似:

$a = mysql_real_escape_string('%!"#¤%&/()=?´`?=)(/&%¤#"!\'\'"\'%');
$query_string = "SELECT * FROM mytable WHERE `column` LIKE '$a'";

这会解决你的问题吗?

答案 3 :(得分:0)

如果您与(模式)比较的那个字段不是一个常量(就像您指定的那个:%!"#¤%&/()=?...),您可以像这样直接在 MySQL 中转义它:

SELECT * FROM `mytable` WHERE `column` LIKE REGEXP_REPLACE(pattern, '([%_])', '\\\\$1');

(其中 pattern 可以是另一列:column2、MySQL 变量或表达式)

这在存储过程/函数中也很有用。