開發者們應該知道,使用那些非標准的SQL命令(比如Oracle、微軟和MySQL等數據庫系統)存在程度相當高的危險。也就是說,從跨平台和遵守標准的角度出發,你應該盡量采用ANSI SQL,它是一種和平台無關的數據庫語言。不管你在使用哪種數據庫系統,如果它完全支持SQL那麼它就應該支持ANSI SQL-92標准。可是,“應該支持”和“確實支持”完全是兩碼事。在進行DBMS跨平台編程的時候,並不是所有的系統都完全支持ANSI SQL標准。這篇文章主旨就是提出使用非標准SQL時所存在的風險及其相關的建議。
別使用存儲過程
在某些編程環境下,出於效率和安全等方面的原因,存儲過程成為程序員開發數據庫應用程序的唯一方法。Visual Basic、C和Java程序員都並不需要了解SQL。然而,在其他某些編程環境下,存儲過程又是完全禁用的。MySQL通常和apache Web服務器組合使用,這是因為這兩種軟件不僅免費、可靠而且功能強大,但是,恰恰是MySQL不支持存儲過程。
--------------------------------------------------------------------------------
存儲過程的定義
所謂存儲過程就是組成一個邏輯單元而且執行特別任務的一組SQL語句。存儲過程用來封裝針對數據庫服務器的一整套操作或查詢。
--------------------------------------------------------------------------------
Oracle和SQL服務器兩者都包括了“內建”的存儲過程,其使用也是很方便的。可是,如果明智的話千萬別指望它們,你無法保證數據庫管理員是否鎖定、刪除或修改了這些存儲過程。如果你發現可用的某些存儲過程正是你需要的,你這才可以在自己的代碼中使用它們的功能。
通常,你能在Oracle或SQL Server上使用存儲過程但在MySQL上則無法利用。如果你確實用到了它們,那麼你得保證自己沒有用到同特定平台相關的命令(以後討論)。
別使用連接
連接是Oracle和SQL Server 這兩種DBMS上令人頭痛的一個問題,因為這兩種系統在連接的概念上有根本的不同。基本上,各個DBMS的連接工作原理不總是一樣的,而且你最終可能會得到意外的結果集合。在我們談論各個系統有關連接的概念差別以及如何解決這些問題之前,你應該理解基本的連接子句:
連接
Join(連接)是從多個數據源獲取數據的SQL數據表創建命令。
等連接
Equi-Join從兩個獨立的數據源獲取數據並把它們組合成一個大表。
內/外連接
內連接(Inner Join)把兩個表的內部列連接起來。外連接把兩個表的外部列連接起來。
左/右連接
左連接(Left Join)連接兩個表左邊的列。右連接則連接兩個表右邊的列。
復合/復雜連接
其他各種連接—左/內、左/外、右/內和右/外等。
反正你得記清楚了,如果你想要自己的應用程序能在各種數據庫服務器上都能工作那麼就別使用連接。
ANSI SQL:CREATE, DROP, ADD, UPDATE, DELETE, INSERT, SELECT
總之,你應當用到的唯一命令如下:
數據定義語言(DDL)下的CREATE 和DROP。
數據操作語言(DML)下的ADD、UPDATE、DELETE和INSERT 。
獲取數據的SELECT。
如果你在這些命令中使用了區分大小寫的表格或字段名,或者這些名字包含了空格或其它特殊字符,那麼你最好用方括號把名字圍起來。這樣做有助於防止非標准字符引發DBMS的不正常反應。
引用的完整性:鍵和數據類型
使用關系數據庫的決定性原因就是明確數據之間的關系而且維持那些關系的完整性。這樣才能讓開發者以最小的冗余性、最高效的方式存儲數據。鍵定義了關系。數據類型定義了存儲和操作數據的規則。這些就是一個數據庫的基本方面,但是具體的語法卻可能因為數據庫的不同而不同。
數據類型
只有很少部分的數據類型得到所有數據庫服務器的支持。每一種DBMS都有它自己的數據類型以及為什麼要這樣使用它們的原因。某些專有數據類型(比如Microsoft Access的AUTONUMBER)用起來確實相當方便。
以下是ANSI數據類型:
BIT, CHARACTER, DATE, DECIMAL, DOUBLE PRECISION, FLOAT, INTEGER, INTERVAL, NUMERIC, REAL, SMALLINT, TIMESTAMP, TIME, VARBIT, VARCHAR, CHAR
以下是Oracle/Access/SQL不支持的“標准”數據類型:
INTERVAL, TIME, VARBIT
只有Oracle才支持DATE,但是以下的“標准”數據類型不被Oracle支持:
BIT, DECIMAL, NUMERIC, TIMESTAMP
以下的“標准”數據類型不被Access支持:
BIT, CHARACTER, DATE, NUMERIC, SMALLINT, TIMESTAMP
這樣,只有以下的數據類型可以保證在各類數據庫上都能使用:
DOUBLE PRECISION, FLOAT, INTEGER, NUMERIC, REAL, SMALLINT, VARCHAR, CHAR
主/外鍵
假設某個表內有兩個字段,創建這個表的語法如下:
CREATE TABLE [MyTable] ([FieldA] VARCHAR, [FIEldB] VARCHAR);
為了添加主鍵以便表內的每一條記錄都唯一標識你可以采用PRIMARY KEY 表達式:
CREATE TABLE [MyTableA] ([RecordID] VARCHAR PRIMARY KEY, [FieldA] VARCHAR, [FIEldB] VARCHAR);
在創建另一個表,其中一個字段索引第1個表,你可以把該字段定義為同第1個表的字段具有關系的外鍵:
CREATE TABLE [MyTableB] ([RecordID] VARCHAR PRIMARY KEY, [FieldA] VARCHAR, [FieldB] VARCHAR, [FieldC] VARCHAR REFERENCES [MyTableA]([FIEldA]))
在以上例子中,所有的字段都是VARCHAR類型;但是你得記住,某一數據類型字段只能索引同一數據類型的字段。
ODBC 和 JDBC
如果你在編寫的應用程序要用到SQL數據庫連接,那麼你可以用ODBC完成該功能。如果它是一個Java應用程序則可以用JDBC(簡而言之就是ODBC的Java接口)。
因為你希望自己的應用程序最好不要引起管理員的注意,所以你應該為你用戶的DBMS包括所有必要的ODBC驅動程序。這樣,如果用戶從一個平台轉移到另一個平台,它們所需要的驅動程序卻已經事先擁有了。
你的應用程序應該通過編程的方式決定當前用到的ODBC驅動程序對應何種DBMS。這樣你才能用上那些數據庫服務器上強大的、同特定平台相關的命令。
另類浏覽器之戰
最流行的浏覽器當然是微軟的Internet Explorer和Netscape的Navigator了。但是,不管你手頭用的是哪一種,它能保證支持現有的所有網站嗎?錯!很多花哨的東西,比如DHtml、框架以及多媒體等等都各自受到兩類浏覽器中非標准的Html標簽的支持。
因為程序在這兩種國際標准的岔路口無所適從,所以你必須為兩種浏覽器編寫代碼或者編寫最具普遍性的功能代碼而放棄大量的動態內容。
數據庫服務器也面臨同樣的問題。ANSI SQL-92是人人贊同的標准。然而,Oracle、微軟以及其他數據庫廠商還自作主張加入了很多破壞SQL代碼的特性。因此,你不僅得編寫遵從基本規范(SQL-92)的代碼,而且的代碼還得根據具體用到的產品實現不同的特性。
在你自己的應用程序內,你必須正確地決定應用程序將使用什麼類型的數據庫,而且數據庫應該定位在哪裡。你還得老練地處理應用程序或用戶產生的任何錯誤。你當然不希望僅僅因為文件被刪除或者網線連接松弛就導致程序崩潰(或服務器崩潰)。在經過精心設計的網絡上,數據庫服務器通常同工作站和Web服務器、應用服務器在物理上相分離,因此斷開連接是很常見的。
小結
作為web開發者,你需要對應用程序使用非標准SQL命令的危險保持高度的小心。這篇文章的中心思想是建議用ANSI SQL編寫跨平台的應用程序。利用ANSI SQL減少商業數據庫系統的非標准方言所帶來的頭疼問題。