【问题标题】:Java / Sql-server parameter binding does not work as expectedJava / Sql-server 参数绑定没有按预期工作
【发布时间】:2019-11-10 10:40:03
【问题描述】:

我们注意到我们的应用程序中有一个关于绑定参数的奇怪行为。我们使用 Java 和 JDBC 连接到 Sql Server 数据库。在表格单元格中,我们有值“μ”,我们将它与绑定参数进行比较,该参数也设置为值“μ”。

现在,在像 "... where value != ?" 这样的 sql 语句中,其中 'value' 是数据库中 'µ' 的值,而 ?绑定变量,它也设置为 'µ',我们注意到我们得到了一条记录,尽管我们希望 'µ' 等于 'µ'。

我们用来填充绑定参数的方法是java.sql.PreparedStatement.setString(int, String)。

Some facts:

μ在不同编码中的字符值为:

ASCII (ISO-8859-1) : 0xB5

UTF-8 : 0xC2B5

UTF-16 (= Java) : 0x00B5

现在我做了一些调查,看看数据库实际看到了哪些字节。因此,我尝试了这样的 sql 语句:

select convert(VARBINARY(MAX), value), --  selects µ from database table
       convert(VARBINARY(MAX), N'µ'),  --  selects µ from literal
       convert(VARBINARY(MAX), ?)      --  selects µ from bind parameter
from ...

三个值的结果是:

B500
B500
C200B500     <-- Here is the problem!

因此,数据库中 µ 的内部表示形式以及 NVARCHAR 文字是 B500。

现在我们无法理解这里发生了什么。我们在 Java 变量中有值“µ”(内部应该是 0x00B5)。当它作为绑定变量传递时,它似乎被转换为 UTF-8(这使得字节序列为 0xC2B5),然后数据库将其视为两个字符,从中生成字符序列 C200B500。

让事情变得更加混乱:

(1) 在另一台具有不同数据库的机器上,相同的代码可以正常工作。三行的结果是B500/B500/B500,所以绑定变量被转换为正确的B500。

(2) 在同一台机器上,相同的数据库但不同的程序(但使用相同的 jdbc 驱动程序库和相同的连接参数)这按预期工作,结果为 B500 /B500/B500。

一些额外的事实,也许它们很重要: 数据库是 Sql Server 2014 Java 是 Java 7 有问题的应用程序是在 Tomcat 7 中运行的 webapp。 jdbc 库是 sqljdbc 4.2

非常感谢任何帮助解决这个问题!

【问题讨论】:

  • 你能发布一个简短但完整的问题重现吗?
  • 是的,请editminimal reproducible example 联系您的问题。您有问题的代码中的某些内容强制使用 UTF-8 编码并将µ 发送为byte[] 而不是String。 (对于 Unicode,SQL Server 不使用 UTF-8;它使用 UTF-16LE。)
  • 您是否尝试过升级到较新版本的驱动程序?支持 Java 7 的 Microsoft SQL Server JDBC 驱动程序的最新版本是 6.4.0。此外,请确保您在代码中使用了正确的 µ 值。可能由于不正确的源编码,该值可能已以 UTF-8 输入,但编译为 windows-1252(因此产生两个字符 µ (0xc2b5))。尝试在您的代码中使用 unicode 转义 \u00B5

标签: java sql-server jdbc unicode binding


【解决方案1】:

我现在找到了解决方案。它根本与 Sql Server 或绑定无关,而是...

Tomcat 7 默认不以 UTF-8 模式运行(我不知道这一点)。我们正在谈论的 µ 来自另一个通过 web 服务调用提供此值的应用程序。但是,this 应用程序默认使用 UTF-8。所以,它正在发送一个 UTF-8 µ,但 web 服务没想到 UTF-8 并认为它会是两个字符,并像这样对待它们,用 0xC2 和 0xB5 的字符填充内部 String 变量(即, 对于 Sql Server, C200B500)。

【讨论】:

  • stackoverflow 专家的问题:我应该如何修改这个问题以使其有用(因为它与最初认为的 Sql Server 无关)?
  • 应该从安全角度探索这个特定区域。
猜你喜欢
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
相关资源
最近更新 更多