作为国内最好的程序员,我想我会问这个问题,希望有人能发现错误,或者告诉我我做错了。
我有一个Flash Builder网站,它试图创建一个搜索功能来搜索我的MYSQL数据库,然后返回结果。
我包含了非空部分,以防用户没有在相关变量中键入任何数据。
但是我得到了这个错误原因:服务器错误MySQL错误-1064:您的SQL语法有错误;查看与MySQL服务器版本对应的手册,了解在第1#0行的"wells AND sex LIKE female"附近使用的正确语法
这是代码
public function searchClients($fname, $lname, $country, $town, $sex) {
$SQLStatment = "SELECT id, fname, lname, sex, country, town, dateofbirth, monthofbirth, yearofbirth FROM $this->tablename";
$WhereClause = "";
$where =" Where ";
if($fname != "NULL") {
$WhereClause.= 'Fname LIKE '.$fname;
}
if($lname != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND lname LIKE ' .$lname;
}
else
{
$WhereClause = 'lname LIKE ' .$lname;
}
}
if($country != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND country LIKE ' .$country;
}
else
{
$WhereClause = 'country LIKE ' .$country;
}
}
if($town != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND town LIKE ' .$town;
}
else
{
$WhereClause = 'town LIKE ' .$town;
}
}
if($sex != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND sex LIKE ' .$sex;
}
else
{
$WhereClause = 'sex LIKE ' .$sex;
}
}
$SQLStatment.= $where;
$SQLStatment.= $WhereClause;
$stmt = mysqli_prepare($this->connection, $SQLStatment);
$this->throwExceptionOnError();
mysqli_stmt_execute($stmt);
$this->throwExceptionOnError();
$rows = array();
mysqli_stmt_bind_result($stmt, $row->ID, $row->fname, $row->lname, $row->sex, $row->country, $row->town, $row->dateofbirth, $row->monthofbirth, $row->yearofbirth);
while (mysqli_stmt_fetch($stmt)) {
$row->fname = ucfirst(substr($row->fname,0,1));
$row->lname = ucfirst($row->lname);
$row->town = ucfirst($row->town);
$row->lname = (($row->fname) . " " . ($row->lname));
$row->yearofbirth = GetAge($row->dateofbirth. '-' .$row->monthofbirth. '-' .$row->yearofbirth);
$row->Pic_loc = "";
$row->Pic_loc= "IMAGES/".($row->ID)."/image01.jpg";
$rows[] = $row;
$row = new stdClass();
mysqli_stmt_bind_result($stmt, $row->ID, $row->fname, $row->lname, $row->sex, $row->country, $row->town, $row->dateofbirth, $row->monthofbirth, $row->yearofbirth);
}
mysqli_stmt_free_result($stmt);
mysqli_close($this->connection);
return $rows;
}
它在我看来不错,但不起作用,有什么建议吗?在代码中指出它的呻吟是
if($town != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND town LIKE ' .$town;
}
else
{
$WhereClause = 'town LIKE ' .$town;
}
}
if($sex != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND sex LIKE ' .$sex;
}
else
{
$WhereClause = 'sex LIKE ' .$sex;
}
}
只是觉得很奇怪,它没有抱怨其他三个if条款,而是抱怨最后两个。
where子句应该是这样的:
$WhereClause .= ' AND sex LIKE "' . mysql_escape_string($sex).'"';
您可以使用准备好的语句/PDO来简化代码并保护应用程序不受SQL注入的影响
您的字符串应该加引号。对where子句进行以下更改:
if($town != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND town LIKE "' .mysql_escape_string($town).'"';
}
else
{
$WhereClause = 'town LIKE "' .mysql_escape_string($town).'"';
}
}
if($sex != "NULL") {
if($WhereClause != "")
{
$WhereClause.= ' AND sex LIKE "' .$sex.'"';
}
else
{
$WhereClause = ' sex LIKE "' .$sex.'"';
}
}
顺便说一句,你应该在你的值周围使用百分比符号
首先,一个调试技巧——当你在动态构建语句时,遇到一个无法立即解决的SQL错误,首先要做的就是打印出构建的语句(请在你未来的SO文章中包括它)。部分看起来像:
SELECT … lname LIKE wells AND sex LIKE female …
从中,你可以看到你的值周围的引号缺失了——应该是:
SELECT … lname LIKE 'wells' AND sex LIKE 'female' … -- quoting non-numeric is NOT optional in SQL
所以,为了运行这个,你可以添加单引号。但仍然存在两个问题,还有第三个潜在问题。
- 这仍然不起作用。我假设通过使用
LIKE
而不是=
,您想要进行子字符串匹配。所以你需要在你的值周围加上百分比符号:lname LIKE '%wells%'
- 您已经在使用准备好的语句,您真的应该使用占位符(例如
lname LIKE ?
)构建查询,然后用这种方式填充。这将为您处理转义,防止SQL注入
潜在的第三个问题是,使用LIKE进行子字符串匹配的性能非常糟糕。这种类型的匹配可以而不是使用索引。您正在进行全表扫描。使用全面的搜索解决方案(Sphinx、全文等)可以解决这个问题(但可能会增加更多的工作)。