当MSSQL查询中的过滤器包含特殊字符时,它们将无法匹配“相同”的字符串。该如何纠正?

时间:2018-10-22 19:46:05

标签: php sql-server character-encoding

我们使用PHP脚本从API读取数据。对于每个返回的记录,我们将来自该记录的字段与MSSQL数据库中的数据进行比较。根据这两个字段(字符串)是否匹配,实现了不同的逻辑。

匹配不区分大小写,我们也不关心尾随/前导空格。

//value of $p['organizationName'] = 'Forté Initiative'
$groupNameForMatching = trim(strtolower($p['organizationName']));

//there is a group name in this table = 'Forté Initiative'
$matchCountPrep=$conn->prepare("SELECT COUNT(*) AS MatchCount FROM schema.table WHERE LOWER(LTRIM(RTRIM(GroupName))) = :OrganizationName);
$matchCountPrep->bindParam(":OrganizationName", $groupNameForMatching);
try {
    $matchCountPrep->execute();
}
catch (PDOException $matchCountError) {
    echo "ERROR: " . $matchCountError->getMessage();
    exit();
}
$matchCount=$matchCountPrep->fetchColumn();

此代码可对所有不包含特殊字符的组正常工作。例如:

“国际象棋俱乐部”和“国际象棋俱乐部”匹配,该组的$ matchCount = 1值。

尽管“FortéInitiative”和“FortéInitiative”虽然是相同的字符串,但还是不匹配。我相信这可能是由于用于字符“é”的字符编码。

我没有数据库服务器或实例的管理或dba访问权限。我确实对执行脚本的Web服务器和PHP配置具有管理员访问权限。但是,此脚本将被迁移到另一个Web服务器,在不久的将来我将无权对其进行管理访问。

由于上述原因,我正在寻找一种代码内解决方案。在查询的filter子句中进行比较时,是否可以对两个字符串进行类似编码的方法?

谢谢您的任何建议。这是我第一次在Stack Overflow上发帖,所以请让我知道我的问题是否有所欠缺,我将进行更新。感谢您的帮助!

编辑: 我在另一个站点上获得了指导,这导致我的代码和两个解决方案出现问题。

问题在于strtolower不是多字节安全函数,并且不会保留本机编码。使用重音符的编码时,该编码已损坏。另外,我在错误的假设下进行操作,即字符串比较将区分大小写。实际上,使用strtolower的全部需求并不存在。

解决方案一:使用mb_strtolower代替strtolower。 mb_strtolower成功保留了编码,并且使用此函数时,MSSQL比较的行为符合预期。

解决方案二:修剪空格后比较字符串,但不强迫比较的任何一侧都小写。即使字符串与大小写严格不匹配,查询的filter子句仍会将字符串视为匹配。注意:默认情况下,这是正确的,但并非在所有环境中都正确,这取决于数据库的排序规则。

0 个答案:

没有答案