2016年11月28日 星期一

ORACLE SQL的字串處理

字元類型是用來表示現實世界自然語言及文字的資料類型,
電腦大部份的運算資源一半以上是用來字串處理。

本章的編排先來認識字元及字串在電腦上是如何表示,
之後再來研究字串的基本操作,
然後獨立一個章節來說明字串模式比對。

抽取子字串

ORACLE語法:

substr(string str, int start, int length)

start 表示起算點,length 是子字串的長度。

T-SQL:

SUBSTRING (value_expression ,start_expression ,length_expression )

位置起算點是 1。


抽取子字串

substring('thomas' from 2 for 3) => hom

substring(string from pattern) => text

抽取匹配 posix 正則表示式的子字串

substring('thomas' from '...$') => mas

substring(string from pattern for escape) => text

抽取匹配SQL正則表示式的子字串

substring('thomas' from '%#"o_a#"_' for '#') => oma



字元(char)
~~~~~~~~~~
在電腦和電信領域的術語中,字元是一個資訊單位。
在使用字母系統或音節文字等的文字的自然語言中,
它大約對應為一個音位或符號。

字元的例子有字母、數字系統或標點符號。

字元通常也包含控制字元,
控制字元並不對應到自然語言中的特定符號,
而是對應到語言中一些用來處理文句的東西。
例如列印機或顯示器的命令,如 return 或 tab。

字串(String)
~~~~~~~~~~~~
字串是由零或多個字元所組成的有限序列,
通常是程式語言中表示文字的資料類型。
其最基本的儲存方式是陣列和鏈結。

字串相等通常定義為長度相等,
並且各個對應位置上的字元都相等。

模式匹配是指找出字串 p 在字串 q 中首次出現的位置。

我們很少操作單一字元,
通常以字串整體作為操作單位,
例如:在字串中尋找某個子字串、求取一個子字串、
在字串的某個位置上插入一個子字串以及刪除一個子字串等。

字元類型(char)
~~~~~~~~~~~~~~
SQL 定義了兩種基本的字元類型:

table.字元類型
名稱                             描述
================================ ======================
character varying(n), varchar(n) 可變長度,有長度限制
character(n), char(n)            固定長度,不足補空白
text                             可變長度,無長度限制
================================ ======================

對 character varying(n) 和 character(n) 而言,
n 是一個正整數,指類型最多儲存 n 字元長字串。
若嘗試儲存更長的字串到此類型的字串裡則會產生一個錯誤,

除非超出長度的字元都是空白,這種情況下該字串將被截斷為最大長度。

若儲存字串的長度比 n 短,
類型 character 將會用空白填滿不足的長度;
而類型為 character varying 的數值將儲存較短的字串,
所以 character varying 比較節省空間。

若強制將字串轉換成 character(n) 或者 character varying(n),
那麼超過長度的字串將被截斷成 n 個字元,而不會拋出錯誤。

char(n) 和 varchar(n) 分別是 character(n) 和 character varying(n) 的別名,

沒有長度定義 n 的 character 等於 character(1);

若不帶長度定義 n 的 character varying,
則該類型接受任何長度的字串。

text 類型,它可以儲存任何長度的字串。
儘管類型 text 不是 SQL 標準,但被很多 SQL 資料庫系統支援。

character 字串都用空白填充到指定的長度 n,
並且以這種方式儲存和顯示。

填充空白在語意上並不重要。

在比較兩個 character 字串時,填充空白會被忽略,
在轉型成其它字串類型時,character 字串空白會被刪除。
但在 character varying 和 text 字串中,
結尾填充空白語意上是有含義的。

這些類型的儲存需求是 4 字元加上實際的字串,
若是 character 的話再加上填充空白。

長字串會自動被系統壓縮,
因此實際儲存空間需求可能會更少些。
長字串也會儲存在後台資料表裡面,
這樣就不會干擾對短字串值的快速訪問。
允許儲存的最長字串大概是 1 GB。

若想儲存沒有特定上限之長字串,
那麼使用 text 或者沒有長度定義詞的 character varying,
而不要選擇一個任意長度限制。

這三種類型之間沒有性能差別,
只不過 character 類型會增加填充空白儲存長度,
沒特別需要的話應該使用 text 或者 character varying,
而不要使用 character。

[string_constant]字串常數
~~~~~~~~~~~~~~~~~~~~~~~~~
SQL 裡的一個字串常數是用單引號「'」包圍的任意字串,
其中包括英數字元 (a-z、A-Z 和 0-9) 以及符號,
如驚歎號 「!」、記號「@」 和數字符號「#」。
一個字串常數如下:

'色不異空空不異色'

空字串用不含任何東西的兩個單引號「''」來表示。

單引號由兩個連續單引號表示,
如敝人女兒蘋果的玩具,其英文句如下:

'Apple''s toy'

任何其它跟在反斜線後面的特殊字元其原來作用會跳脫而只有字面意義,
所以單引號可用反斜線「\\」也來跳脫,因此上例可改寫如下:

'Apple\\'s toy'

其它跳脫字元如下:
\\b 表退格字元,\\f 表進紙,\\n 表換行,\\r 表回車,\\t 表分欄。

反斜線字元由兩個反斜線表「\\\\」表示。

八進制數表示語法為 \\xxx,xxx 是 ascii 碼的八進位代碼。

編碼為零的字元不能出現在字串常數中。

兩個至少有一個換行空白分隔字串常數會被連接,並當成一個常數處理。
比如:

select 'foo'
'bar';

等效於

select 'foobar';



select 'foo'      'bar';

是非法語法。

table[escape_chars].SQL 跳脫字元表
字串  符號        例句
===== =========== =========================
''    單引號      'Apple''s toy'
/'    單引號      'Apple\'s toy'
\b    退格字元
\f    進紙
\n    換行
\r    回車
\t    分欄
\\    反斜線
\xxx  八進位代碼
===== =========== =========================

字串函數和運算子
~~~~~~~~~~~~~~~~
字串包括 character, character varying,和 text 類型值。
除非另外說明,所有下面列出的函數都可以處理這些類型,

不過要小心的是,在使用 character 類型的時候,
填充空白的潛在影響。

通常這裡描述的函數也能用於非字串類型,
我們只要先把那些資料轉化為字串資料表現形式就可以了。
有些函數還可以處理位串類型。

SQL 定義了一些字串函數,
它們有指定的語法,
裡面是用某種特定的關鍵字,
而不是逗號來分隔參數。

字串連接(concatenation)
~~~~~~~~~~~~~~~~~~~~~~~
字串串接,又稱字串相加、連接、串連、相連,
指將兩個字串作首尾相接。

例如「色不異空」和「空不異色」串接後便成了「色不異空空不異色」。

SQL 使用「||」作為字串連接運算子,
如下例:

code[concatenation.sql].
select '色不異空' || '空不異色' => '色不異空空不異色'
::

bit_length
~~~~~~~~~~
字串所佔的 byte 長度,如下例:

select bit_length('jose') => 32

char_length
~~~~~~~~~~~
char_length(string) 或 character_length(string)
 
字串中的字元個數,如下例:  

char_length('jose') => 4

octet_length
~~~~~~~~~~~~
octet_length(string) => integer

字串中的字元數

octet_length('jose') => 4

convert
~~~~~~~
convert(string using conversion_name)

使用指定的轉換名字改變編碼。轉換可以透過 create conversion 定義。
當然系統裡有一些預定義的轉換名字。
參閱 table 9-7 獲取可用的轉換名。  

convert('sql tutorial' using iso_8859_1_to_utf_8)

傳回 unicode (utf-8) 編碼的 'sql tutorial'

lower
~~~~~
lower(string)
 
把字串轉化為小寫

lower('Tom') => tom

upper
~~~~~
upper(string) => text

把字串轉化為大寫。

upper('tom') => TOM

position
~~~~~~~~
position(substring in string) => integer

定義的子字串的位置

position('om' in 'thomas') => 3

overlay
~~~~~~~
overlay(string placing string from integer \[for integer\])

替換子字串  

overlay('txxxxas' placing 'hom' from 2 for 4) => thomas

replace(char, str1, str2)

position
~~~~~~~~
position(substring in string) => integer

指定的子字串的位置  

position('om' in 'thomas') => 3

trim
~~~~
trim(\[leading | trailing | both\] \[characters\] from string) => text

從字串 string 的開頭、結尾或兩邊
刪除只包含 characters 「預設是一個空白」的最長的字串。

trim(both 'x' from 'xtomxx')i => tom

substring
~~~~~~~~~
substring(string \[from integer\] \[for integer\]) => text  

substr(str, int, int) => text

抽取子字串  

substring('thomas' from 2 for 3) => hom

substring(string from pattern) => text

抽取匹配 posix 正則表示式的子字串  

substring('thomas' from '...$') => mas

substring(string from pattern for escape) => text  

抽取匹配SQL正則表示式的子字串

substring('thomas' from '%#"o_a#"_' for '#') => oma

T-SQL:

SUBSTRING (value_expression ,start_expression ,length_expression )

位置起算點是 1。

其它
~~~~
set sqlblanklines on
讓 SQL\*plus 可辨識含空白行的字串值。

沒有留言:

張貼留言