为什么我得到 VARCHAR 比较的意外结果?
Why I'm getting unexpected results of VARCHAR comparison?
我正在执行这样的句子。
fld1 VARCHAR(5);
Select * from MyTable where fld1 = 'HELLOWORLD';
在 table 中只有 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;}
}
}
"HELLO" 的长度为 5 个字符,这是存储在数据库中的内容,因为 NAME 被定义为 VARCHAR(5)。剩下的 if 形成是 "trimmed"/"Dropped"/"Discarded" 因此 "World" 从数据库的角度来看不存在。
我记得有同样的效果;诊断为警告,sqlstate='01004' "The value of a string was truncated when assigned to another string data type with a shorter length." on OPEN。
我不太记得我阅读的文档是什么,作为我进行更改的原因,但参数标记正确表示较大的字符串值,从而避免了问题[即为了防止选择较短的值],我基本上编码了 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 中显示的用法解释为指定 未类型化参数标记 "The data type of an untyped parameter marker is provided by context." [= 谓词中的未类型化参数标记OP … where FLD1 = ?
中的 14=] 语句建立为与 FLD1 列相同的数据类型,显示为 FLD1 VARCHAR(5)
。 OPEN
和 EXECUTE
文档分别解释了如何实现 参数标记替换 的详细信息。为方便起见,我将在此处解释文档中的一些文本,但还包括以下三个文档链接:
Given the Parameter Marker P
, the value of the corresponding variable V
is assigned to the target variable created for P
using storage assignment rules as described in Assignments and comparisons. However, unlike noted with those storage assignment rules, if V
is a string, then the value assigned to the target variable for P
when the statement is executed, will be truncated (without an error) whenever that string-value is longer than the length attribute of the target variable for P
; or, whenever that string-value is shorter than the length attribute of the target variable for P
, the value for P
is padded with blanks.
在下面的每个文档参考中,搜索 Parameter Marker、cast 或 Notes[=53] =] 以获得最具体的细节;目前可以在 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
我正在执行这样的句子。
fld1 VARCHAR(5);
Select * from MyTable where fld1 = 'HELLOWORLD';
在 table 中只有 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;}
}
}
"HELLO" 的长度为 5 个字符,这是存储在数据库中的内容,因为 NAME 被定义为 VARCHAR(5)。剩下的 if 形成是 "trimmed"/"Dropped"/"Discarded" 因此 "World" 从数据库的角度来看不存在。
我记得有同样的效果;诊断为警告,sqlstate='01004' "The value of a string was truncated when assigned to another string data type with a shorter length." on OPEN。
我不太记得我阅读的文档是什么,作为我进行更改的原因,但参数标记正确表示较大的字符串值,从而避免了问题[即为了防止选择较短的值],我基本上编码了 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 中显示的用法解释为指定 未类型化参数标记 "The data type of an untyped parameter marker is provided by context." [= 谓词中的未类型化参数标记OP … where FLD1 = ?
中的 14=] 语句建立为与 FLD1 列相同的数据类型,显示为 FLD1 VARCHAR(5)
。 OPEN
和 EXECUTE
文档分别解释了如何实现 参数标记替换 的详细信息。为方便起见,我将在此处解释文档中的一些文本,但还包括以下三个文档链接:
Given the Parameter Marker
P
, the value of the corresponding variableV
is assigned to the target variable created forP
using storage assignment rules as described in Assignments and comparisons. However, unlike noted with those storage assignment rules, ifV
is a string, then the value assigned to the target variable forP
when the statement is executed, will be truncated (without an error) whenever that string-value is longer than the length attribute of the target variable forP
; or, whenever that string-value is shorter than the length attribute of the target variable forP
, the value forP
is padded with blanks.
在下面的每个文档参考中,搜索 Parameter Marker、cast 或 Notes[=53] =] 以获得最具体的细节;目前可以在 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