通過錯誤的sql來測試推理sql的解析過程

jeanron100發表於2015-11-28
在學習Oracle的時候,必然會接觸到sql解析的過程。這個過程大體是這樣的步驟。
1.對sql的文法檢查,檢視是否有文法錯誤,比如from,select拼寫錯誤等。
2.在資料字典裡校驗sql涉及的物件是否存在。
3.將物件進行名稱轉換,比如同義詞轉義成對應的物件。比如select * from t t是一個同義詞指向hr.test
4.檢查語句的使用者是否具有訪問物件的許可權
5.生成執行計劃
6.將遊標產生執行計劃,sql文字裝載入library cache所在的heap中。
這個過程看起來比較容易理解,但是實際中我們也不能死記硬背,如果想推理一下其中的有些步驟,其實不用很精細的trace也可以辦到。我們就用最簡單的sql語句來測試。
當然思路需要轉換,要測試的是存在問題的sql語句,看oracle的編譯器會給我們什麼樣的解釋。
首先準備一個測試表
create table test (id number,name varchar2(30));
準備好之後,就開始測試一下。不過思路是用有問題的語句來測試,來推理。
下面的語句存在很多的問題,來看看oracle的反應。
select1 id1 from2 test1 where3 id1='aaa' group by4 id1 order  by5 id1
*
ERROR at line 1:
ORA-24333: zero iteration count
首先解析發現select的語句錯誤其實後面from,where,group by,order by都有錯誤。但是首先發現是select的部分。可見解析還是從左至右的方向來做文法解析。
接著修復select的文法錯誤,來繼續看看。
select id1 from test1 where3 id1='aaa' group by4 id1 order  by5 id1
                             *
ERROR at line 1:
ORA-00933: SQL command not properly ended
這個時候錯誤指向了id1而沒有指向where3,可見編譯器在處理的時候可能不知道該怎麼處理了。這一點上出乎我的意料。修復where的文法錯誤繼續測試。
select id1 from test1 where id1='aaa' group by4 id1 order  by5 id1
                                           *
ERROR at line 1:
ORA-00924: missing BY keyword
這個時候直接指向了group by的部分。通過這三個例子可以基本推理出文法解析是從左至右。對於是否存在表,是否欄位存在問題都先不會解析。
然後我們修復了group by,order by的文法錯誤,繼續測試。
select id1 from test1 where id1='aaa' group by id1 order  by id1
                *
ERROR at line 1:
ORA-00942: table or view does not exist
發現錯誤指向了test1,發現沒有這個表。可見在文法解析之後開始校驗是否存在這個表。這個時候還沒有開始校驗欄位的情況。
修復了表名的錯誤,繼續測試。
select id1 from test where id1='aaa' group by id1 order  by id1
                                                *
ERROR at line 1:
ORA-00904: "ID1": invalid identifier
發現這個時候是在解析group by 的欄位名,對於select,where,order by中的先不解析。
然後修復group by中的錯誤,繼續測試。
select id1 from test where id1='aaa' group by id order  by id1
                           *
ERROR at line 1:
ORA-00904: "ID1": invalid identifier
發現解析到了where 子句中的欄位值。這個時候select,order by中還沒有開始解析。
修復where子句中的問題,繼續測試。
select id1 from test where id1='aaa' group by id order  by id1
       *
ERROR at line 1:
ORA-00904: "ID1": invalid identifier
這個時候錯誤就指向了select子句,這個時候就剩下了order by的部分。
修復select的部分。繼續測試。
SQL> select id from test where id='aaa' group by id order  by id1;
select id from test where id='aaa' group by id order  by id1
                                                         *
ERROR at line 1:
ORA-00904: "ID1": invalid identifier
終於指向了order by,可見order by的部分是語句執行的最後的部分。
通過上面的錯誤測試,可以發現能夠基本得到語句解析中的處理順序。
我們更深一步。看看如果欄位id為number,賦予varchar2的資料,是否會在解析的時候校驗出來。
SQL>  select id from test where id='aaa' group by id order  by id;        
 select id from test where id='aaa' group by id order  by id
                              *
ERROR at line 1:
ORA-01722: invalid number
這個時候發現錯誤已經在校驗資料的型別了。
怎麼看出在解析的時候是否校驗了資料型別呢,別急,來做一個操作即可。
SQL> delete from test ;
1 row deleted.
然後再次執行上面的語句。
SQL> select id from test where id='aaa' group by id order  by id;
no rows selected
就會發現這個時候oracle好像處理不了這種場景了。
好了,oracle編譯器已經很強大了。我們就最後以一個基本正常的語句結束。
SQL> select id from test where id='100' group by id order  by id;
no rows selected

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1848816/,如需轉載,請註明出處,否則將追究法律責任。

相關文章