天天看點

簡單對比MySQL和Oracle中的一個sql解析細節

SQL的文法解析器是一個很強大的内置工具集,裡面會涉及到很多的編譯原理的相關知識,文法分析,詞法分析。。一大堆看起來很理論的東東,不過看起來枯燥之餘,它們的價值也更加明顯。

借用一下網絡中的原話:如果我們考究一下曆史,就會發現很多被稱為程式設計大師的人都是編譯領域的高手.寫出第一個微型機上運作的Basic語言的比爾蓋茨,設計出Delphi的Borland的”世界上最厲害的程式員”, Sun的JAVA之父, 貝爾實驗室的C++之父

起點提得有些高了,今天和大家分享的案例是一個很簡單的sql語句,在MySQL中能夠解析出問題,但在Oracle中就可以成功解析,通過這一個細節也能夠看出一些Oracle和MySQL中的一些差别。

需要運作的語句如下:

SELECT THREAD_ID, threads.NAME, SUM (COUNT_STAR) AS Totalcount, SUM(SUM_TIMER_WAIT) AS Totaltime

FROM performance_schema.events_waits_summary_by_thread_by_event_name

INNER JOIN performance_schema.threads USING (THREAD_ID)

WHERE threads.NAME LIKE 'thread/sql/slave\-%'

GROUP BY THREAD_ID, threads.NAME;

ERROR 1630 (42000): FUNCTION performance.sum does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual

乍一看這個錯誤,感覺一定是哪裡出了問題,自己找了一會沒發現明顯的語句問題,但是從錯誤來看問題似乎發生在sum字眼的附近。

簡單把第1行中的

SUM (COUNT_STAR) AS Totalcount 改為SUM(COUNT_STAR) AS Totalcount 問題就引刃而解了。可以看出問題是一個很細小的問題,嚴格來說,确實是語句寫得不夠嚴謹。但在我的印象中Oracle似乎對這鐘情況也是手到擒來,印象中沒有出現過此類問題。

我們來簡單在MySQL和Oracle中模拟一下這個問題,看看結果如何。

在MySQL中

create table parse_test ( id int, name varchar(30));

insert into parse_test values(1,'aa');

insert into parse_test values(2,'bb');

commit;

mysql> select count(id) from parse_test;

+-----------+

| count(id) |

|         2 |

1 row in set (0.00 sec)

mysql> select count (id) from parse_test;

ERROR 1630 (42000): FUNCTION test.count does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual

在Oracle中就沒有任何問題了。

create table parse_test( id number, name varchar2(30));

select count(id)from parse_test;

 COUNT(ID)

----------

         2

select count (id) from parse_test;

抛開Oracle解析複雜sql語句的優勢,可以看出Oracle在這種細節方面确實支援的力度要高一些。

不過最開始在MySQL出錯的語句在放到Oracle裡面(如果假設表結構資料都存在),也一定運作不了。原因就在于Oracle中定義的表明長度最大是30位,但是在MySQL中支援的要多不少,達64位。

mysql> create table events_waits_summary_by_thread_by_event_name567890123456789012345 ( id int, name varchar(30));

ERROR 1059 (42000): Identifier name 'events_waits_summary_by_thread_by_event_name567890123456789012345' is too long

mysql> select length('events_waits_summary_by_thread_by_event_name567890123456789012345');

+-----------------------------------------------------------------------------+

| length('events_waits_summary_by_thread_by_event_name567890123456789012345') |

|                                                                          65 |

1 row in set (0.01 sec)

當然了我也是到此為止我也是撿個小石頭,弄點兒水花,對于sql解析器更深入的問題,如果細究,從MySQL代碼層面能夠分析出問題來就一個基本目标了。