在CHAR(3)列上使用预准备语句时的不同匹配

时间:2014-11-04 12:12:18

标签: oracle oracle10g oracle-sqldeveloper oracle-xe

我必须将CHAR(1 CHAR)列更宽,我忘了将列类型更改为VARCHAR2

DUPLICADO CHAR(3 CHAR)

当我的PHP应用程序不再能找到完全匹配时,我发现错误,例如:

SELECT *
FROM NUMEROS
WHERE DUPLICADO = :foo

... :foo#4时未找到3-char填充#4值。但是,我最初在SQL Developer中调试查询时遇到了红鲱鱼,因为在查询中注入原始值会找到匹配项!

SELECT *
FROM NUMEROS
WHERE DUPLICADO = '#4'

为什么我与第二个查询匹配?为什么准备好的陈述有所作为?

1 个答案:

答案 0 :(得分:1)

为了扩展我的评论,我在文档中找到了一些解释blankpadded和nonpadded比较的区别:

http://docs.oracle.com/database/121/SQLRF/sql_elements002.htm#BABJBDGB

如果比较中的两个值(等号的两边)都具有数据类型CHAR或NCHAR或是文字字符串,则Oracle选择空白填充比较。这意味着如果长度不同,那么用空白填充短的长度直到长度相同。

如果DUPLICADO列为CHAR(3),则值'#4'将作为三个字符'#4 '存储在列中(请注意空白为第三个字符。)当您执行DUPLICADO = '#4'规则规定Oracle将使用空白填充比较,因此将文字'#4'空白,直到它与列的长度相同。所以它实际上变成了DUPLICADO = '#4 '

但是当你执行DUPLICADO = :foo时,它将取决于绑定变量的数据类型。如果数据类型为CHAR,它还将执行blankpadded比较。但是如果数据类型是VARCHAR2,那么Oracle将使用非填充比较,然后由您决定是否在必要时进行空白填充。

根据客户端或客户端语言,您可以指定绑定变量的数据类型,从而根据需要进行空白填充或非填充比较。

SQL Developer可能是一种特殊情况,可能不允许您指定数据类型 - 它可能默认绑定变量始终是数据类型VARCHAR2。我不太了解SQL Developer对此有所了解; - )