我相信很多人接觸這些概念的時候一頭霧水。要把這些概念理清楚真不是件容易的事,哪像原始社會,只要能分清楚什麼能吃什麼不能吃就行了。
但是我始終堅信,每一個概念的產生必然是因為碰到了無法解決的問題。換句話說,如果沒有它,必然會導致某些問題難以解決。所以我想從這個角度切入,希望能把這幾個復雜而暧昧的多角關系從最實用的角度來闡述清楚。
在問題的最初,我們假定的數據庫什麼都沒有。
數據庫對象。首先,數據庫對象是比較容易懂的。所有的表,視圖,存儲過程,觸發器都稱為數據庫對象。
我們可以拿一個網站來做類比。一個網站包含很多的網頁,圖片,腳本文件,我們姑且稱它為網站對象。
顯然,我們不可能把所有的網站對象都放到一個文件夾下面,同樣道理,數據庫對象也不可能象煮餃子一樣就在數據庫裡這麼一鍋出。對於網站,我們通常會把不同模塊的文件放在不同的子文件夾下,那麼誰是存放數據庫對象的文件夾呢?答案就是:架構(Schema).
架構(Schema)。微軟的官方說明(MSDN): "數據庫架構是一個獨立於數據庫用戶的非重復命名空間,您可以將架構視為對象的容器",詳細參考http://technet.microsoft.com/zh-cn/library/ms190387.ASPx.我們知道,在Java中,命名空間名其實就是文件夾名。因此我們非常明確一點:一個對象只能屬於一個架構,就像一個文件只能存放於一個文件夾中一樣。與文件夾不同的是,架構是不能嵌套的,如此而已。因此,我們要訪問一個數據庫對象的時候,通常應該是引用它的全名"架構名. 對象名",這點非常類似C#。
問:為什麼有的時候寫select * from tablename也可以執行呢?
答:這是因為default schema.當只寫tablename時,SQL Server會自動加上當前登錄用戶的default schema。
如果此表不屬於當前登錄用戶的default schema,將會提示無效的對象名。
加上shcema以後成功。
不過我們也可以更改當前用戶的default schema,這時就可以不用加前綴了。
Code
當然,我們也可以改變此表的schema,相當於把這個表放到另一個文件夾,從emdbuser放到dbo中。
Code
以上兩種作法在真實項目中都不應該作為解決方案,因為它改變了原來的設置。我們最希望的是,即使我們以dbo登陸,我們也可以偽裝成emdbuser來操作數據庫對象,偽裝完了還能切換回來。在SQL Server中,剛好有這樣的語句實現這個功能。
Code 這種機制被稱為“上下文切換”,操作完以後,可以實用REVERT命令切換回來。(.Net中也有類似的機制,它們有共同的一個名稱叫做Impersonate,
角色扮演。)
詳細解釋參照MSDNhttp://msdn.microsoft.com/zh-cn/library/bb153640(SQL.90).ASPx
問:如何根據表名獲取一個表的Schema呢?
答:可以參照以下SQL語句從sys.objects視圖和sys.schemas視圖中獲取。
Code
結論:架構就是數據庫對象的容器。數據庫對象是飲料,架構就是杯子,誰拿杯子喝水呢?當然是用戶,那麼是不是一個用戶只能用一個杯子,一個杯子是不是從一而終,只能給一個人用呢?。請看第二節。