请考虑以下情形:有一个SQL表,它将数据保存在多个不相容的字符集中。一个例子是一个表,其中列为latin-1,一列为KOR,另一列为JIS。
虽然此示例可能不符合此附加要求,但请假设不存在包含所有三列中使用的所有符号的字符集。例如,您如何有效地在此处输入新数据?
与SQL数据库的连接拥有自己的字符集,可以使用语句对其进行修改,但显然,单个字符集中的简单命令不足以在一个语句中输入单行数据。
我意识到不建议使用许多遗留字符集,特别是对于Web应用程序。但是,问题仍然与旧版或继承软件非常相关。
答案 0 :(得分:0)
使用介绍
通过使用特殊的“介绍人”变量,可以在同一个语句中组合多个字符集。例如,发送到SQL数据库:
INSERT INTO `table` (`row1`, `row2`) VALUES (_sjis'<S1>', _cp1250'<S2>');
在此示例中,查询告诉SQL服务器使用Shift-JIS对数据进行编码,并使用cp1250对数据进行编码。无论连接的字符集是什么,都会写入查询。
如果查询中的字符集与列的字符集不匹配,则SQL服务器将尝试转换每对不匹配的字符集。如果转换失败,则查询将失败并显示错误(将<data>
,<column>
和<row>
替换为值)
ERROR 1366 (HY000): Incorrect string value: '<data>' for column '<column>' at row <row>
现在假设连接使用简单的ASCII字符集。这意味着如果在shift-JIS字符串中碰巧有一个0x27字节'
符号(由于它是非ASCII兼容的多字节编码,它可能完全不是所讨论的字符串中的实际引号),那么该语句可能导致SQL注入问题。
因此,需要“逃避”有问题的字符串。当我们处理一堆不同的字符集时,即:
这很快就会变得非常令人头疼,因此大多数现代编程语言都有特殊的SQL连接器库来处理这个问题。不幸的是,SQL不支持参数化查询中的引入者,这意味着,在这种情况下,我们不能使用这些方便的工具,并且必须回归到更古老的方法。需要做的是在连接的字符集中手动转义字符串。 PHP中的一个例子:
// Assume $PDO is a PDO object, $shiftjis_string is our JIS string,
// and $cp1250_string is a string in CP1250.
$v1 = $PDO->quote($shiftjis_string);
$v2 = $PDO->quote($cp1250_string);
$query = "INSERT INTO `table` (`row1`, `row2`) VALUES _sjis'{$v1}', _cp1250'{$v2}'; ";
$result = $PDO->query($query);
只要我们注意不要更改quote()
和query()
调用之间的基础连接的字符集,就不应该有任何注入可用性。
备注强>
这个答案是我对如何做到的最好的猜测,但可能存在更好的方法。