Oracle 12.1 对 VARCHAR2 列使用字符串文字时的奇怪计划 (NLS_COMP=BINARY_AI)
Oracle 12.1 strange plan when using string literal against VARCHAR2 column (NLS_COMP=BINARY_AI)
我在 Oracle 12.1 中遇到一个非常具体的问题,涉及在 VARCHAR2(2500)
列上应用 SQL WHERE
子句中以 space 结尾的字符串文字的处理(名为 'NOTES')。
因为我需要不区分大小写和重音的字符串比较,所以我在登录数据库触发器中更改了 NLS_COMP
和 NLS_SORT
:
ALTER SESSION SET NLS_COMP='LINGUISTIC';
ALTER SESSION SET NLS_SORT='BINARY_AI';
然后,如果我尝试这个(注意 'cholera' 末尾的 ' ' space,因为 space 出现在table 数据,我无法更改它,因为我只有 table):
的只读访问权限
SELECT NOTES FROM DECCODESIDC WHERE NOTES='cholera ';
到目前为止,还不错,它 return 是唯一符合条件的行 ('Choléra ')
但是如果我基于 table 创建一个视图,并且我应用相同的标准,它不会 return 任何东西:
SELECT 注释来自(SELECT 来自 DECCODESIDC 的注释)WHERE NOTES='cholera ';
我注意到 explain plan
在两个查询之间是不同的
这是第一个查询解释计划:
注意 HEXTORAW
的最后 6 位数字:61 20 00 -> 61='a', 20=' ' (space), 00=结束
第二个:
注意 HEXTORAW
的最后 6 位数字:72 61 00 -> 72='r', 61='a', 00=end
正如我们所见,Oracle 自动添加的 HEXTORAW
函数在第二个查询中删除了尾随 space,但在第一个查询中没有...
我知道字符串文字被 Oracle 视为 CHAR
并且受 space 填充的约束,但在这种情况下,字符串文字与 VARCHAR2
类型进行比较专栏...它没有解释为什么执行计划不同...
我是不是遗漏了什么或者是 Oracle 中的错误?
Benoit
ps:事实是我不会手动编写此类查询,而是依靠 Entity Framework 和 Oracle Managed Drivers,所以我没有太多关于查询重写的选项:(
ps2:作为临时解决方法,我在我的视图中的每个 VARCHAR2 列上添加了对 TRIM oracle 函数的调用,但它在性能方面不是最理想的...
对于面临相同问题的任何人:我应用了补丁包 12.1.0.2.170117,现在一切似乎都正常...:/
我在 Oracle 12.1 中遇到一个非常具体的问题,涉及在 VARCHAR2(2500)
列上应用 SQL WHERE
子句中以 space 结尾的字符串文字的处理(名为 'NOTES')。
因为我需要不区分大小写和重音的字符串比较,所以我在登录数据库触发器中更改了 NLS_COMP
和 NLS_SORT
:
ALTER SESSION SET NLS_COMP='LINGUISTIC';
ALTER SESSION SET NLS_SORT='BINARY_AI';
然后,如果我尝试这个(注意 'cholera' 末尾的 ' ' space,因为 space 出现在table 数据,我无法更改它,因为我只有 table):
的只读访问权限SELECT NOTES FROM DECCODESIDC WHERE NOTES='cholera ';
到目前为止,还不错,它 return 是唯一符合条件的行 ('Choléra ')
但是如果我基于 table 创建一个视图,并且我应用相同的标准,它不会 return 任何东西:
SELECT 注释来自(SELECT 来自 DECCODESIDC 的注释)WHERE NOTES='cholera ';
我注意到 explain plan
在两个查询之间是不同的
这是第一个查询解释计划:
注意 HEXTORAW
的最后 6 位数字:61 20 00 -> 61='a', 20=' ' (space), 00=结束
第二个:
注意 HEXTORAW
的最后 6 位数字:72 61 00 -> 72='r', 61='a', 00=end
正如我们所见,Oracle 自动添加的 HEXTORAW
函数在第二个查询中删除了尾随 space,但在第一个查询中没有...
我知道字符串文字被 Oracle 视为 CHAR
并且受 space 填充的约束,但在这种情况下,字符串文字与 VARCHAR2
类型进行比较专栏...它没有解释为什么执行计划不同...
我是不是遗漏了什么或者是 Oracle 中的错误?
Benoit
ps:事实是我不会手动编写此类查询,而是依靠 Entity Framework 和 Oracle Managed Drivers,所以我没有太多关于查询重写的选项:(
ps2:作为临时解决方法,我在我的视图中的每个 VARCHAR2 列上添加了对 TRIM oracle 函数的调用,但它在性能方面不是最理想的...
对于面临相同问题的任何人:我应用了补丁包 12.1.0.2.170117,现在一切似乎都正常...:/