如何将多个不兼容的字符集传递给mySQL?

时间:2017-06-26 18:25:42

标签: sql character-encoding

请考虑以下情形:有一个SQL表,它将数据保存在多个不相容的字符集中。一个例子是一个表,其中列为latin-1,一列为KOR,另一列为JIS。

虽然此示例可能不符合此附加要求,但请假设不存在包含所有三列中使用的所有符号的字符集。例如,您如何有效地在此处输入新数据?

与SQL数据库的连接拥有自己的字符集,可以使用语句对其进行修改,但显然,单个字符集中的简单命令不足以在一个语句中输入单行数据。

我意识到不建议使用许多遗留字符集,特别是对于Web应用程序。但是,问题仍然与旧版或继承软件非常相关。

1 个答案:

答案 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注入问题。

因此,需要“逃避”有问题的字符串。当我们处理一堆不同的字符集时,即:

  1. 程序代码的字符集。
  2. 数据库列的字符集
  3. 连接的字符集。
  4. “SQL客户端”的字符集。
  5. SQL主机系统的字符集,或“默认”。
  6. 这很快就会变得非常令人头疼,因此大多数现代编程语言都有特殊的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()调用之间的基础连接的字符集,就不应该有任何注入可用性。

    备注

    这个答案是我对如何做到的最好的猜测,但可能存在更好的方法。