1. 程式人生 > >ORACLE 動態SQL中的多個單引號

ORACLE 動態SQL中的多個單引號

今天在專案中遇到動態拼sql的語句,

語句如下:

v_sql := 'update Table_Test t '

        ||' set t.field1 = ''' || 變數1 || ''','  -- v_BalRuleID || v_BalanceSeq || ''','

        ||' t.field2 = ''' || 變數2 || ''','

        ||' t.field3 = ''' || 變數3 || ''','

        ||' t.field4 = 1,'

        ||' t.field5 = ' || 變數4            

        ||' where t.field6 = ''' || 變數5 || ''''

        ||'  and  INSTRb( '''|| 變數6 ||''',t.field7 ) >0 ';

    execute immediate v_sql;

於是對其中多個連續的單引號感到奇怪,google後,終於恍然大悟,下面把總結貼出來:

 在ORACLE中,單引號有兩個作用,一是字串是由單引號引用,二是轉義。單引號的使用是就近配對,即就近原則。而在單引號充當轉義角色時相對不好理解。
  1、從第二個單引號開始被視為轉義符,如果第二個單引號後面還有單引號(哪怕只有一個)。

SQL> SELECT '''' FROM DUAL;
 
''
--
'
 
為了證實結果是被第二個單引號轉義的第三個單引號(既:SELECT '''' FROM DUAL;),我們做如下兩個測試:
 
SQL> SELECT ''' FROM DUAL;
ERROR:
ORA-01756: 括號內的字串沒有正確結束
 
 
相信大家對這樣的錯誤不陌生吧
 
SQL> SELECT 'SDLF FROM DUAL;
ERROR:
ORA-01756: 括號內的字串沒有正確結束
 

   也就是說,當第二個單引號充當轉義角色,第三個單引號被轉義,(既:select '' ' from dual;)自然就缺少與第一個單引號匹配的單引號了,出現了孤立的單引號
下面的兩個實驗就更加支援了上面的結論。
 
SQL> SELECT ' '' ' FROM DUAL;
 
''''
------
'
 
SQL> SELECT '' '' FROM DUAL;
SELECT '' '' FROM DUAL
          *
ERROR 位於第 1 行:
ORA-00923: 未找到預期 FROM 關鍵字
 
 
 
對於第一個:SELECT ' '' ' FROM DUAL;
對於第二個:不存在轉義。
 
上面的這兩個實驗其實也是單引號轉義與非轉義的一個性質:轉義是密集的,也就是說,如果單引號出現在轉義的位置上,而該單引號後面緊跟(緊跟的定義為:兩個單引號之間是零距離的)的不是單引號,這個時候單引號就不在充當轉義的角色,而是與它前面的配對。

 
2、連線符‘||’導致了新一輪的轉義:連線符號‘||’左右的單引號沒有任何的關係,除非‘||’是作為字串的一部分(這在動態SQL中很常見)。
 

SQL> SELECT 'ORACLE'||'''' FROM DUAL;
 
'ORACLE'||''
----------
ORACLE'
 個人理解,'ORACLE'||'''' 後面的“''''”應該認為是一個字串(即前後單引號,中間是“''”串,而中間又是密集單引號,因此第一個為轉義功能)
SQL> SELECT 'ORACLE''''' FROM DUAL;
 
'ORACLE'''''
------------
ORACLE''

對於第一個,前兩個單引號配對,後面四個單引號按照上面的第一條原則分配,既:SELECT 'ORACLE'||'''' FROM DUAL;
對於第二個,由於第二個單引號後面存在單引號,所以就不與第一個配對,而是充當了轉義的角色。既:SELECT 'ORACLE''''' FROM DUAL;