我在这里遇到一个问题,看起来像MariaDB中的一个错误,但在将它发布到MariaDB错误数据库之前我想在这里发布,也许我做错了。
使用以下代码可以轻松复制问题:
public static void main(String[] args) throws ReplicationException, SQLException {
byte[] cb3 = {-61, -92, 98, -29, -125, -70, -61, -87}; //equals to "äb?é", with “?” being a japanese character
String corrupt = new String(cb3, Charsets.UTF_8);
MariaDB db = new MariaDB();
Connection conn = db.getConnection();
//byte[] latinBytes = corrupt.getBytes(Charset.forName("ISO-8859-1")); //workaround
//corrupt = new String(latinBytes, Charset.forName("ISO-8859-1")); //workaround
PreparedStatement sqlInsert = conn.prepareStatement("insert into prep values (?)");
sqlInsert.setString(1, corrupt);
sqlInsert.execute();
conn.commit();
System.out.println("insert ok");
PreparedStatement sqlSelect = conn.prepareStatement("select * from prep where text=? ");
sqlSelect.setString(1, corrupt);
sqlSelect.execute();
}
在我的MariaDB(有字符集latin1!)上,有一个表格准备:“create table prep(text varchar(10));” 当我运行此代码时,插入工作完美:日语字符转换为“?”,如预期的那样。 但是,sqlSelect根本不起作用,并产生令人担心的错误消息“非法混合排序(latin1_general_cs,IMPLICIT)和(utf8_general_ci,COERCIBLE)操作'='”。
如果我将sql更改为“select * from prep where text =?collate latin1_general_cs”,我收到错误消息“COLLATION'latin1_general_cs'对CHARACTER SET'utf8'无效”。因此我得出结论,我的绑定变量“corrupt”没有转换为where子句的latin1。但是,我期望这种转换,因为它适用于插入。
有一种可行的解决方法:如果激活两行“// workaround”,则在将数据库提供给数据库之前,将在java中转换该字符串。但是,我觉得这不应该是必要的。
在oracle数据库上运行相同的代码不会产生错误。有人可以在mysql数据库上运行吗?
那么,这看起来像是一个错误,或者我错过了什么。
其他信息:
MariaDB版本10.0.14,适用于java的MariaDB客户端库:1.1.7
jdbc连接字符串如下所示:
"jdbc:mariadb://localhost:3306/myDb?rewriteBatchedStatements=true&useServerPrepStmts=false"
要启动数据库,我使用默认的“my-large.ini” 我使用以下代码创建了数据库:
create database myDb
DEFAULT CHARACTER SET latin1
COLLATE latin1_general_cs;
更新:我向mariaDB团队提交了一份错误报告: https://mariadb.atlassian.net/browse/CONJ-117
答案 0 :(得分:1)
在使用MariaDB和MySQL进行测试代码试验后,我可以确认它们的行为似乎有所不同。但是,我不一定称它为MariaDB中的“bug”。
它似乎与数据库服务器本身的响应不同。我尝试使用MariaDB Java Client 1.7和MySQL Connector / J 5.1.27将更改应用于MariaDB 10.0.13服务器,并且它们都给出了相同的结果:MariaDB能够自动翻译来自的第一个,第二个和第四个字符UTF-8到Latin1,但它在第三个(日语)字符U + 30FA(UTF-8中的0xE3 0x83 0xBA)上被阻塞,因为没有Latin1等价物。
这是有道理的。在某些情况下,MySQL可能很方便(并且静默地)将所有不可翻译的字符映射到'?'
,但这可能并不总是可取的。您设计的解决方法是告诉Java明确强制非Latin1字符'?'
,然后将 传递给MariaDB。你觉得它没有必要,但我不确定我同意。
因此,它是否是MariaDB中的“bug”实际上取决于MariaDB是否正在运行“as designed”。换句话说,仅仅因为MariaDB的行为与MySQL不同,并不一定会成为MariaDB中的错误。例如,在MariaDB 5.5.31中,他们改变了CAST()的行为来解决二进制字符串文字的解释问题,结果是
这引入了与以前版本的MariaDB以及所有MySQL版本
的不兼容性
也就是说,您可以随时将您的问题报告为MariaDB错误并查看它们的响应方式。