【问题标题】:Why I'm getting unexpected results of VARCHAR comparison?为什么我得到 VARCHAR 比较的意外结果?
【发布时间】:2016-09-27 19:31:35
【问题描述】:

我正在执行这样的句子。

fld1 VARCHAR(5);

Select * from MyTable where fld1 = 'HELLOWORLD';

表中只有 fld1='HELLO',由于某种原因,结果集给我的结果行是 fld1='HELLO'。

如果 fld1 是 VARCHAR 5,显然是在削减 'HELLOWORLD' 的值,为什么查询不按字面意思获取所有值?

我的方法:

public void Consulta(){
    COB_ConexionModulo connPool = null;
    COB_ResultadoConexion rc    = null;
    Connection con      = null;
    StringBuffer sbQry = new StringBuffer();
    PreparedStatement pstm  = null;
    ResultSet rs            = null;
    COB_Utils util = new COB_Utils();

    try {
        connPool    = COB_ConexionModulo.instance();
        rc          = connPool.getConnection();
        con         = rc.getConexion();

        if(!(con == null)){                                                           
            sbQry = new StringBuffer("SELECT NAME FROM TEST.MYTABLE WHERE NAME = ?");

            pstm = con.prepareStatement(sbQry.toString());
            pstm.setString(1, "HELLOWORLD");

            util.setInicioEjecucion();
            rs = pstm.executeQuery();
            util.imprimeTiempoEjecucion(MSINF,sbQry.toString());  

            while (rs.next()){
                System.err.println(rs.getString("NAME"));
            }
        } else {
            logger.info(MSINF + "No hay conexion");
        }
    } catch (Exception e) {
        logger.error(MSERR + "Consulta()_" + e);
    }finally {
        try {if (con != null) {con.close();con = null;}} catch (SQLException sqle) {con = null;}
    }
}

Images in order: 1.- Table Script 2.- Table Values 3.- Query Result.

【问题讨论】:

  • 你所描述的不应该发生(事实上,当我尝试使用 SQL 重现它时它不会发生)。您可能想要创建并发布一个完整 最小示例来演示此行为,并提及您的 DB2 版本和平台。我怀疑你的 Java 代码有错误。
  • 你使用的是什么 JDBC 驱动程序?
  • 我正在使用 com.ibm.as400.access.AS400JDBCDriver
  • 驱动程序似乎有缺陷。如果绑定参数值被截断,标准 DB2 JCC 驱动程序将引发异常。 @CRPence 关于原因和解决方案是正确的。
  • 显然是的,已经使用 2 个不同的 Web 服务器 IBM WebSphere Application Server、6.0.2.37 和 WebLogic Server 版本:12.2.1.0.0 使用相同的驱动程序进行了测试,结果相同。

标签: java db2 ibm-midrange weblogic12c db2-400


【解决方案1】:

我记得同样的效果;诊断为警告,sqlstate='01004'“当分配给另一个长度较短的字符串数据类型时,字符串的值被截断。”打开。
我不记得我阅读的文档是什么,作为我进行更改的原因,但参数标记正确表示更大的字符串值,从而避免了问题 [即为了防止选择较短的值],我基本上编写了 OP 的代码 [尽管将 25 调整为所需的值;当 DDL 仍然是 NAME VARCHAR(5)] 时,任何六个或更多就足够了:

"SELECT NAME FROM TEST.MYTABLE WHERE NAME = CAST( ? AS VARCHAR(25) )"

或者,当然,不太可取:

"SELECT NAME FROM TEST.MYTABLE WHERE CAST( NAME AS VARCHAR(25) ) = ?"

2016 年 9 月 30 日附录
PREPARE 的文档将 OP 中显示的用法解释为指定 无类型参数标记,“无类型参数标记的数据类型由 context 提供。 "来自 OP … where FLD1 = ?SELECT 语句的谓词中的无类型参数标记被建立为与 FLD1 列相同的数据类型,显示为 FLD1 VARCHAR(5)OPENEXECUTE 文档分别解释了如何实现参数标记替换的详细信息。为方便起见,我将在此处解释文档中的一些文本,但还包括三个文档链接:

给定参数标记P,对应变量V的值被分配给使用storage为P创建的目标变量Assignments and comparisons 中描述的分配规则然而,与那些存储分配规则不同,if V 是一个字符串,然后在执行语句时分配给P 的目标变量的值,只要字符串值长于P 的目标变量的长度属性,就会截断没有错误); ,只要该字符串值比P 的目标变量的长度属性短,P 的值就会用空格填充。

在下面的每个文档参考中,搜索 Parameter MarkercastNotes 中的任何一个以获取最具体的详细信息;目前可以在 Notes 部分找到详细信息:
IBM i 7.2->Database->Reference->SQL reference->Statements->PREPARE
IBM i 7.2->Database->Reference->SQL reference->Statements->EXECUTE
IBM i 7.2->Database->Reference->SQL reference->Statements->OPEN

【讨论】:

  • 感谢 CRPence,感谢您的帮助。
  • 备案:如果有人理解该场景是[与驱动程序]的缺陷,那么请不要考虑 我的经验 [没有任何实际文档支持的链接作为一项要求] 作为证据,该效果是无缺陷的。我在自己的代码中所做的可能只不过是一种规避,也许正确的行为是 Mustaccio 在对 OP 的评论中首先提到的;即我可能记错了医生指示我这样做。
  • 有点相似(相关?) -- APAR SE26512 -- 将参数标记转换为适当的数据类型是一种规避。
  • 这是预期行为的根本原因。准备好语句时,数据库没有关于可能的未来参数数据类型的信息,因此它从运算符另一端的值(即数据库列)派生参数的类型。如果您知道参数数据类型可能与列数据类型不匹配,那么向查询编译器提供数据类型信息的正确(也是唯一)方法是通过显式CAST,因此这不是“规避”。正确的驱动程序行为应该是抛出异常,如果...
  • (cont.) .. 绑定时参数值被截断。 IBM i Access JDBC 驱动程序的行为似乎不正确。无论哪种情况,使用CAST 都是合适的解决方案。
【解决方案2】:

“HELLO”的长度为 5 个字符,存储在 DB 中,因为 NAME 被定义为 VARCHAR(5)。剩余的如果形成是“修剪”/“丢弃”/“丢弃”,因此从 DB 的角度来看,“世界”不存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    • 2021-07-10
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-08
    相关资源
    最近更新 更多