【问题标题】:Erlang Emysql encoding difference between prepared and regular Query准备好的查询和常规查询之间的Erlang Emysql编码差异
【发布时间】:2012-03-30 00:40:01
【问题描述】:

我写了一个关于 emysql 编码的问题,得到了正确的答案here。 答案指出了另一个问题...

我正在尝试将 iPhone 表情符号存储到数据库中...

当我这样做时:

Query = io_lib:format("UPDATE Users SET c=\"~s\" WHERE id=~B", [C, Id]),
emysql:execute(mydb, Query).

一切正常...

但是有:

emysql:prepare(update_c, <<"UPDATE Users SET c=? WHERE id=?">>),
emysql:execute(mydb, update_c, [C, Id]).

我正在检索 Mojibake。 编辑使用正确的术语

我正在联系:

 emysql:add_pool(my_db, 3, "login", "password", "db.mydomain.com", 3306, "MyTable", latin1)

不幸的是,我不能使用 utf8,因为以前的软件使用数据库并以这种方式存储表情符号,如果我使用 utf8,它将适用于新系统,但不适用于旧系统插入的行。

编辑:

我真的很想使用prepared statement,这样可以有效地防止SQL注入。

【问题讨论】:

  • 你能限定“胡言乱语”吗,例如你收到 Mojibake 还是只是错误?
  • gibberish = Mojibake,是的......但只有准备好的语句,现在,我正在使用非准备好的语句,使用 mysql_util:encode() 来确保没有注入可能,但是我真的很想使用准备好的语句。

标签: mysql utf-8 erlang prepared-statement latin1


【解决方案1】:

编辑:应该在 253b7f94f9b04526e6868d7b693e6e9ee41de374 中修复。感谢您的反馈。 https://github.com/Eonblast/Emysql/commit/253b7f94f9b04526e6868d7b693e6e9ee41de374


我相信这是 Emysql 中的一个错误,我想我已经修复了它。仍在进行单元测试,所以一切都说得通。我会在它发布到 github 时通知你。

我为此开了一个问题:https://github.com/Eonblast/Emysql/issues/24

本质上,您是在欺骗驱动程序和数据库,因为您打开了与 latin-1 的连接,但数据库是 utf-8。然后你就被自动转换绊倒了。

不过,我认为你是对的,驱动程序应该尊重你将连接设置为 latin-1 而不是自动转换为 utf-8 的魔法。如果你在 github 上阅读 Eonblast/Emysql 的 issue #14,你会发现我一直怀疑自动转换是个坏主意。

但是,仅仅因为转换的单元测试现在被炸毁了四倍(并提出了一些相当无趣但令人难以置信的边缘问题,我无法理解),我认为欺骗数据库你这样做的方式同样是个坏主意。如果可以的话,你应该清理它而不是依靠中间的机制来保持。 MySQL 中有多个级别发生转换。如您所知,您可以将连接、数据库以及表设置为字符集。这是产生错误的好方法。你能描述为什么你不能吗?因为您无法控制并且必须对编码视而不见?我想知道是否有一个真实的案例,没有这个黑客你就活不下去。

不管怎样,您对 latin-1 连接设置的抱怨可能表明了消除 Emysql 中字符转换中所有或大部分猜测的方法。非常感谢,我希望今天晚些时候能为您提供解决方案。

亨宁

【讨论】:

  • 感谢 Henning,我也发现了这个“错误功能”,我会密切关注 github。关于我对 utf8 使用 latin-1 连接这一事实,我知道这是一个坏主意。不幸的是我别无选择,我拿起了这个项目并用 Erlang 从头开始​​重做,但我现在无法更改数据库。但是我会通过将“on prod”迁移到更可集群的东西来慢慢清理它,比如 Cassandra,甚至可能是 Mnesia。感谢您确认问题! +1
【解决方案2】:

只需将您的表格转换为 UTF-8:

ALTER TABLE Users CONVERT TO CHARACTER SET utf8;

然后您可以将 utf-8 用于新数据,旧数据也将转换为 UTF-8。

【讨论】:

  • Users 表已经是 utf8 字符集,但这不是真正的问题......我的问题是关于为什么准备好的语句使用 utf8,因为我明确要求 emysql 使用 latin1 连接到数据库字符集。
  • 好吧,如果我正确理解 erlang,字符串是 ISO8859-1(拉丁)编码,而二进制文件是 UTF-8。所以:“Hi”是拉丁文,但 > 是 utf-8。如果你指示 emysql 使用 utf-8 连接会发生什么?
  • 如果我使用 UTF8 连接到数据库,我可以使用新软件正确添加/检索,唯一的问题是我无法正确检索数据库中已有的数据(我得到 Mojibake 数据)是用以前的软件插入的。不幸的是,我需要正确检索旧数据。
  • 实际上,我想知道为什么它可以与未准备好的语句一起正常工作,尽管我使用 emysql_util:encode() 来避免 SQL 注入,但使用准备好的语句,它不会插入正确地在 latin1
猜你喜欢
  • 1970-01-01
  • 2013-12-25
  • 2011-07-13
  • 2020-11-08
  • 2016-11-21
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多