在學習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
*
ORA-00933: SQL command not properly ended
這個時候錯誤指向了id1而沒有指向where3,可見編譯器在處理的時候可能不知道該怎麼處理了。這一點上出乎我的意料。修複where的文法錯誤繼續測試。
select id1 from test1 where id1='aaa' group by4 id1 order by5 id1
*
ORA-00924: missing BY keyword
這個時候直接指向了group by的部分。通過這三個例子可以基本推理出文法解析是從左至右。對于是否存在表,是否字段存在問題都先不會解析。
然後我們修複了group by,order by的文法錯誤,繼續測試。
select id1 from test1 where id1='aaa' group by id1 order by id1
*
ORA-00942: table or view does not exist
發現錯誤指向了test1,發現沒有這個表。可見在文法解析之後開始校驗是否存在這個表。這個時候還沒有開始校驗字段的情況。
修複了表名的錯誤,繼續測試。
select id1 from test where id1='aaa' group by id1 order by id1
*
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
*
發現解析到了where 子句中的字段值。這個時候select,order by中還沒有開始解析。
修複where子句中的問題,繼續測試。
*
這個時候錯誤就指向了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
*
終于指向了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
*
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;