問題解決——Sqlplus與換行前空格(二)
下面實驗,使用Linux客戶端,在Linux上執行程式碼,觀察現象。如果現象相同,就證明問題與OS差異無關。
[oracle@oracle11g ~]$ pwd
/u01/oracle
[oracle@oracle11g ~]$ cd ..
[oracle@oracle11g u01]$ mkdir testscript --建立一個單獨目錄,儲存同步指令碼
[oracle@oracle11g u01]$ cd testscript
[oracle@oracle11g testscript]$
進行試驗。
[oracle@oracle11g testscript]$ sqlplus /nolog
SQL*Plus: Release 11.2.0.1.0 Production on Sun Mar 13 11:25:30 2011
Copyright (c) 1982, 2009, Oracle. All rights reserved.
SQL> conn scott/tiger@wilson;
Connected.
SQL> conn scott/tiger@wilson
Connected.
SQL> set serveroutput on size 10000;
SQL> set echo off
SQL> set feedback off
SQL>
SQL> spool script.sql
SQL> declare
2 vc_sql varchar2(2000);
3 source_rec all_col_comments%rowtype;
4 target_rec all_col_comments%rowtype;
5 begin
6 --Get Source Info
7 select *
8 into source_rec
9 from all_col_comments
10 where table_name='T1' and COLUMN_NAME='COMM';
11
12 --Get Target Info
13 select *
14 into target_rec
15 from all_col_comments
16 where table_name='T2' and COLUMN_NAME='COMM';
17
18 if (source_rec.comments=target_rec.comments) then
19 dbms_output.put_line('Two Objects Comments are equal !');
20 else
21 vc_sql := 'comment on column '||target_rec.table_name||'.'
22 ||target_rec.column_name
23 ||' is '''
24 ||source_rec.comments||'''';
25 dbms_output.put_line(vc_sql);
26 --execute immediate vc_sql;
27 end if;
28 end;
29 /
comment on column T2.COMM is 'ISO Country
Char Only;'
SQL> spool off;
SQL>
在Linux環境上,生成指令碼中空格同樣存在。
--執行結果
[oracle@oracle11g testscript]$ ls -l
total 4
-rw-r--r-- 1 oracle oinstall 984 Mar 13 11:26 script.sql
[oracle@oracle11g testscript]$ sqlplus /nolog
SQL*Plus: Release 11.2.0.1.0 Production on Sun Mar 13 11:32:32 2011
Copyright (c) 1982, 2009, Oracle. All rights reserved.
SQL> conn scott/tiger@wilson
Connected.
SQL> @script.sql
Comment created.
檢查執行效果。
SQL> select table_name, comments, dump(comments, 1016) from all_col_comments where table_name in ('T1','T2');
TABLE_NAME COMMENTS DUMP(COMMENTS,1016)
------------------------- --------------------------------------------------------------------------------
T2 ISO Country Typ=1 Len=22 CharacterSet=AL32UTF8: 49,53,4f,20,43,6f,75,6e,74,72,79,a,43,68,61,
Char Only;
T1 ISO Country Typ=1 Len=23 CharacterSet=AL32UTF8: 49,53,4f,20,43,6f,75,6e,74,72,79,20,a,43,68,
Char Only;
可見,在Linux平臺上進行試驗,同樣會出現空格刪除的情況。由此我們也可以徹底排除OS差異引起問題的猜測。
額外:在Windows平臺的Oracle上,筆者也進行的相同實驗,結論相同。篇幅原因,就不累述了。
排除了OS原因,只有可能是提交SQL的工具手段原因。我們觀察到,出現空格刪除現象的提交方式,是透過載入執行指令碼到sqlplus,或者直接在sqlplus提示符下執行。而不發生刪除現象的提交,都是繞開sqlplus透過SQL Windows或者PL/SQL Developer的GUI介面方式提交。
這樣,原因就可以猜到了。首先是sqlplus對載入檔案命令列的過程中,因為對文字型別sql指令碼內部結構的“不信任”,會自動把每行資料進行一種trim操作,刪除兩端的空格。之後,再執行這個刪除空格結果。sqlplus使用同樣的方式執行命令列。如果在命令列後輸入空格後回車,該工具會自動的將空格刪除。見下面實驗。
SQL> create table t (ch varchar2(100));
Table created
Executed in 0.19 seconds
--插入一個留有空格的字串
SQL> insert into t values ('blank23
2 df');
1 row inserted
SQL> commit;
Commit complete
SQL> select * from t;
CH
---------------------
blank23
df
進行測算。
SQL> col ch for a10;
SQL> col len for a15;
SQL> col dumps for a30;
SQL> select ch,length(ch) len, dump(ch,1016) dumps from t;
CH LEN DUMPS
---------- --------------- ------------------------------
blank23 10 Typ=1 Len=10 CharacterSet=ZHS1
df 6GBK: 62,6c,61,6e,6b,32,33,a,6
4,66
結論和我們的猜想一樣,九個字元和一個換行符,構成了長度為10的字串。看來sqlplus以及他的模仿產品均是這樣。
同樣的結構,如果我們使用pl/sql developer中的SQL Windows執行,結果如何呢?
--執行命令
insert into t values ('kk
k')
SQL> select ch,length(ch) len, dump(ch,1016) dumps from t;
CH LEN DUMPS
---------- --------------- ------------------------------------------------------------
blank23 10 Typ=1 Len=10 CharacterSet=ZHS16GBK: 62,6c,61,6e,6b,32,33,a,6
df 4,66
kk 4 Typ=1 Len=4 CharacterSet=ZHS16GBK: 6b,6b,a,6b
k
Executed in 0.02 seconds
很遺憾,SQL Windows也是採用此種方法。那麼,只有使用PL/SQL指令碼執行了。下面試著書寫程式碼。
declare
vc_sql varchar2(100);
vc_str varchar2(10);
begin
--定義一個帶換行的回車符;
vc_str := 'dk
lf';
vc_sql := 'insert into t values (:1) ';
execute immediate vc_sql
using vc_str;
commit;
end;
/
執行。
SQL>
PL/SQL procedure successfully completed
SQL> select ch,length(ch) len, dump(ch,1016) dumps from t;
CH LEN DUMPS
---------- --------------- ------------------------------------------------------------
dk 7 Typ=1 Len=7 CharacterSet=ZHS16GBK: 64,6b,a,20,20,6c,66
lf
Executed in 0.01 seconds
同樣,透過pl/sql指令碼執行,但是經過sqlplus,都會將末尾空格刪除。看來,如果是一些語義重要的欄位,如很長的varchar2型別,還要避免使用sqlplus進行提交。
最後,我們存在兩個疑惑,這裡進行以下說明。
首先,既然透過sqlplus是不能進行換行前空格處理的,那麼原始的那個comments是如果新增進去的呢?考慮到開發人員使用pl/sql developer的GUI工具進行建表操作。可能是開發工具在此處是使用直接的提交語句方式給Oracle處理引擎,繞開了sqlplus的語句處理過程。
其次,那麼是不是所有這種換行前空格都要被刪除呢?藉助pl/sql字串變數,和直接提交,是可以避免這種事情發生的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-689811/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 解決eslint空格報錯等問題EsLint
- 解決docker換源問題Docker
- strace解決sqlplus登陸緩慢的問題一例SQL
- Oracle:sqlplus查詢出的中文是亂碼問題的解決(轉)OracleSQL
- 磁碟問題定位與解決
- base64碼通過http傳輸 +號變 空格 問題解決HTTP
- Maven解決repository不更換的問題Maven
- [每日一題] 第十題:替換空格每日一題
- 【問題解決】使用YYYY-MM-dd時間轉換問題
- 空格在程式碼中變成其他字元或者亂碼問題解決方法字元
- 全域性替換 ‘/home’ 為 ‘/’ 的問題解決!
- ES系列二之常見問題解決
- 二進位制方式解決 power 問題
- [20221203]sqlplus set trimspool 問題.txtSQL
- [20221202]sqlplus set trimout 問題.txtSQL
- 解決訪問 GitHub 與 clone 很慢的問題Github
- 解決訪問Github與clone很慢的問題Github
- 解決scanf遇空格停止
- @AllArgsConstructor與@Value共用的問題解決Struct
- 快取穿透問題與解決方法快取穿透
- IDEA解決java註釋頂格、xml註釋右對齊+無空格問題IdeaJavaXML
- shell去掉echo和cat 的行前空格或製表符
- 替換空格
- 解決webpack-dev-server代理常切換問題WebdevServer
- Bigkey問題的解決思路與方式探索
- 解決叢集 Yellow 與 Red 的問題
- thymeleaf手動渲染@{}的問題與解決
- java學習中問題與解決方式Java
- Ajax跨越問題原因分析與解決思路
- 換IP經常出現的問題及其解決方案
- 解決macOS新建txt文件在Windows下不換行問題MacWindows
- App\User 替換為 App\Models\User 的問題解決!APP
- 2162: 練9.1 字元菱形 【空格問題】字元
- [20190108]rlwrap sqlplus tee相關問題.txtSQL
- Django在Linux上uwsgi 與nginx的問題與解決DjangoLinuxNginx
- 解決django 2.2與mysql相容性問題DjangoMySql
- mysql主從複製配置與問題解決MySql
- 解決問題: go get certificate signed by unknown authority 換個代理或者Go
- 使用二分法來解決的問題