暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 白色空间错误

askTom 2017-11-08
357

问题描述

当我们从一个数据库 (Oracle 11.2.0.3.0) 转移到另一个数据库 (Oracle 11.2.4.0) 时,我注意到我们的Oracle数据库中有一个奇怪的错误。数据库服务器位于不同的数据中心,具有不同的操作系统和支持团队。所以版本不是唯一改变的。

所以,这是我面临的错误: 当我执行这个小SQL语句,我得到不同的结果:

从双选择 “你好”;

在旧数据库上,输出为: “你好”
在新数据库上,输出为: “您好 [这里有很多空白,但我不知道如何在Ask Tom上显示它们]”

这些空白是从哪里来的?

我在12.10.0.30版本中使用TOAD for Oracle。

和另一个测试:

选择 '| | 假人 | |' | | 'Hello' | | '从对偶;
从对偶中选择 “|” | | 假人 | | “|”;
选择 “|” | | “你好” | | “|” 从对偶;

结果是:
"| X | 你好 |"
"| X |"
“| 您好 | [这里有很多空白,但我不知道如何在Ask Tom上显示它们]”
有趣的是,它适用于第一个SQL,但是第三个SQL又充满了空白。

我提供了一个LiveSQL链接,您也可以在其中重现此行为。但是您不会在浏览器中看到它,您必须下载csv结果文件并在ex中打开它。记事本。

更新:
-------
我真的很抱歉,这是我的错,它不能在实时系统上复制...不知道我在编辑中看到了什么...,对不起!

商业案例是这样的:
我们执行select语句,将结果存储到CSV文件,然后从CSV文件导入。我已经更新了LiveSQL的一个 (希望) 更好的解释。

使用TOAD,SQL * Plus在我的本地计算机上以及使用Java软件在我们的Linux计算机上可复制。
On my local machine I could connect to the old Oracle database, where the 从双选择 “你好”; statement delivers a result without trailing whitespaces.

可能的解决方案:
------------------
DB参数 *.cursor_sharing在旧数据库上是 “精确的”,在新数据库上是 “强制的”。因此,我们也必须将其更改为 “EXCACT”。

但是为什么会有这样一个带有 “力” 的bug?有什么好的解释吗?

专家解答

所以。

当您将cursor_sharing设置为force时,Oracle数据库将所有文字转换为绑定变量。因此,选择不同字符串的两个其他相同语句成为相同的语句。

较短的字符串绑定到varchar2(32)。这会导致一些客户端将这些读取为32个长度的字符串,从而导致您看到的空白填充:

SQL> exec dbms_monitor.session_trace_enable();

PL/SQL procedure successfully completed.

SQL> alter session set cursor_sharing = force;

Session altered.

SQL>
SQL> select /*+ force */'Hellooooooooooooo' from dual;

'HELLOOOOOOOOOOOOO'
--------------------------------
Hellooooooooooooo

SQL> select /*+ force */'Hello' from dual;

'HELLO'
--------------------------------
Hello

SQL>
SQL> alter session set cursor_sharing = exact;

Session altered.

SQL>
SQL> select /*+ exact */'Hellooooooooooooo' from dual;

'HELLOOOOOOOOOOOO
-----------------
Hellooooooooooooo

SQL> select /*+ exact */'Hello' from dual;

'HELL
-----
Hello


请注意,两个强制声明的破折号都是32!但是当你有精确的cursor_sharing时,完全匹配所选字符串的长度。

在跟踪文件中查找,“force” 语句仅出现一次:

select /*+ force */:"SYS_B_0"
from
 dual


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        4      0.00       0.00          0          0          0           2
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        8      0.00       0.00          0          0          0           2


注意解析和执行两者 = 2。

但是确切的陈述是分开出现的:

select /*+ exact */'Hellooooooooooooo'
from
 dual


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0          0          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          0          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 112
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  FAST DUAL  (cr=0 pr=0 pw=0 time=7 us cost=2 size=0 card=1)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  SQL*Net message from client                     2        0.20          0.39
********************************************************************************

SQL ID: g9d9mghmsardu Plan Hash: 308129442

select /*+ exact */'Hello'
from
 dual


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0          0          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          0          0           1


我怎么知道它绑定到varchar2(32)?

好吧,你可以用这样的语句查找它:

select s.sql_text, b.name, b.datatype_string, b.max_length 
from   v$sql s
left join v$sql_bind_capture b
on     s.sql_id = b.sql_id
where  s.sql_text like '%+ force%'
and    s.sql_text not like '%not this%';

SQL_TEXT                                  NAME       DATATYPE_STRING   MAX_LENGTH   
select /*+ force */:"SYS_B_0" from dual   :SYS_B_0   VARCHAR2(32)                32

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论