问题描述
当我们从一个数据库 (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?有什么好的解释吗?
所以,这是我面临的错误: 当我执行这个小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个长度的字符串,从而导致您看到的空白填充:
请注意,两个强制声明的破折号都是32!但是当你有精确的cursor_sharing时,完全匹配所选字符串的长度。
在跟踪文件中查找,“force” 语句仅出现一次:
注意解析和执行两者 = 2。
但是确切的陈述是分开出现的:
我怎么知道它绑定到varchar2(32)?
好吧,你可以用这样的语句查找它:
当您将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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




