題外話:最近看到各種吐槽.NET怎么落寞、.NET怎么不行了、.NET工資低的帖子。我也吐槽一句:一個程序猿的自身價值不是由他選擇了哪一門技術來決定,而是由他自身能創造出什么價值來決定。
在進入本篇內容之前,這里有幾個問題:
1.一般程序猿都知道怎樣創建、修改、登錄賬號,但知不知道登陸賬號存儲在哪個表或者視圖?
2.數據庫中其實存在登錄賬號和用戶兩個概念,你能解釋清楚這兩個概念嗎?
3.對於一個登錄賬號,我們可以為他設置哪些權限?
4.你清不清楚數據庫信息存儲在哪些表或試圖?
5.我們可以給登錄賬號設置權限,但清不清楚具體有哪兩種權限?
如果你回答不上,那接下來的內容有必要知道。如果都能很清楚的回答出來,接下來的內容你可以直接忽略。
前一段時間寫了Sql Server來龍去脈系列的前四篇,包括數據庫的框架和配置、查詢過程跟蹤、數據庫庫和文件。說實話, 當時寫的時候自己都是一知半解,有些內容了解得不是很清楚。近來我一直沒有更新系列的后續內容,而是把時間用來寫一個小的數據庫權限管理系統,為得就是把前面寫的系列隨筆涉及到的知識鞏固下。系統的主界面如下圖:
界面上的導航菜單也就是這篇隨筆的主要內容,包括登陸賬號、數據庫、權限控制。權限控制包括了服務權限和數據庫權限。需要說明的是:界面上的說的用戶實際是登陸賬號,而數據庫用戶和賬號是有區別的。
像登錄賬號、數據庫以及權限等系統元數據一般是不允許直接操作的,那么我們怎樣讀取以及怎樣修改更新這些元數據?Sql Server為開發人員提供了系統視圖、存儲過程、DDL(數據定義語言)用來讀取以及更改系統元數據。DDL全稱是Data Definition Laguage,它的語法包括我們經常用到的CREATE、ALTER、DROP等。開發人員在MSDN上也能找到對應的在線說明。下面分別給出幫助鏈接:
1.系統視圖:https://msdn.microsoft.com/zh-cn/library/ms177862(v=sql.120).aspx,查看元數據一般都是通過目錄視圖查找。
2.存儲過程:https://msdn.microsoft.com/zh-cn/library/ms187961(v=sql.120).aspx
3.DDL:https://msdn.microsoft.com/zh-cn/library/ff848799(v=sql.120).aspx
接下來我們分別介紹前面說的登錄賬號管理、數據庫管理以及權限管理。
登錄賬號管理
賬號查詢
管理維護Sql Server數據庫,一般都是使用Sql Server Management Studio。當我們成功鏈接數據庫實例后,可通過Security/Logins管理登錄賬號。如下圖:
這里有個疑問:這些賬號信息是從哪里查出來的?之前我們介紹了系統元數據可通過系統視圖查詢。登錄賬號的目錄視圖是sys.syslogins,我們可通過下面的查詢語句查詢登錄賬號信息:
select * from sys.syslogins, 字段說明:https://msdn.microsoft.com/zh-cn/library/ms178593(v=sql.120).aspx
執行結果如下:
返回的結果包括了name、dbname、password、language,這幾個字段是經常涉及到的,每行數據不止上面這些字段,還包括服務權限字段,如下:
至於這些字段有什么用,后面介紹權限時再說明。在我自己寫的數據管理系統中就是通過從sys.syslogins查詢數據。系統界面如下:
創建賬號
知道數據怎么查詢后,我們繼續看怎樣創建登錄賬號,下圖就是創建登錄賬號的界面:
界面包括了登錄名、密碼、默認數據庫、默認語言,登陸名和密碼操作者自己輸入,但默認數據庫和默認語言只能選擇數據庫存在的。所有我們必須得知道怎樣查詢數據庫表和語言表,這里就提出了 另外兩個目錄視圖sys.databases、sys.syslanguages。通過名字也能知道這兩個表分別存儲的是數據庫和語言的元數據。執行下面語句查詢數據庫中存在哪些數據庫:
select name, database_id, owner_sid, create_date from sys.databases,字段說明:https://msdn.microsoft.com/zh-cn/library/ms178534(v=sql.120).aspx
結果如下:
結果中包含owner_sid字段,這個字段就是存儲的登錄賬號的系統ID,一般是哪個登錄賬號創建的數據庫,這個數據庫就屬於這個創建它的登陸賬號。執行下面語句:
select db.name, db.database_id, lg.name, db.create_date from sys.databases db inner join sys.syslogins lg on db.owner_sid = lg.sid
結果如下:
通過結果一目了然的看出每個數據庫的所屬者。記得在初始化系統數據庫腳本時,一般都會判斷數據庫是否存在。現在我們知道可以通過sys.databases視圖查看數據庫信息,那么我們也通過以下語句判斷一個數據庫是否存在:
if exists (select * from sys.databases where name = '數據庫名') drop database [數據庫名]
sys.syslanguages的數據比較簡單,這里就不再說明。可通過https://msdn.microsoft.com/zh-cn/library/ms190303(v=sql.120).aspx查看字段解釋。現在再回到之前的創建界面,數據庫和語言我們都能提供出來了,登錄名和密碼也輸入了。但怎么把數據插入到數據庫?這里就提到前面說的數據定義語言DDL,用CREATE LOGIN關鍵字創建登錄賬號。先看下在系統中我拼湊的SQL語句:
string sql = string.Format("CREATE LOGIN [{3}] WITH PASSWORD = N'{0}', DEFAULT_DATABASE =[{1}], DEFAULT_LANGUAGE =[{2}]" , login.Password, login.DbName, login.Laguage, login.Name);
語句很簡單,PASSWORD設置密碼,DEFAULT_DATABASE設置默認數據庫,DEFAULT_LANGUAGE設置默認語言。當然創建登錄賬號的參數肯定不止這些,我們可通過https://msdn.microsoft.com/zh-cn/library/ms189751(v=sql.120).aspx查看創建登錄賬號所有的參數。
修改賬號
現在已經知道怎樣創建登錄賬號了,但有些時候我們需要修改登錄賬號的某些信息,例如密碼、默認數據庫。修改登錄賬號使用DDL語言的ALTER LOGIN關鍵字。修改語句和創建語句極其相似,只是把CREAT關鍵字改成了ALTER。看看下面的系統修改登錄賬號代碼:
string sql = string.Format("ALTER LOGIN {0} WITH PASSWORD = N'{1}', DEFAULT_DATABASE =[{2}],DEFAULT_LANGUAGE =[{3}]", name, login.Password, login.DbName, login.Laguage) //參考:https://msdn.microsoft.com/zh-cn/library/ms189828(v=sql.120).aspx刪除賬號
最后還剩下刪除操作,我們知道刪除表的語句一般是 DROP TABLE [表名],而刪除登陸賬號也相似,執行:
DROP LOGIN [登錄名], https://msdn.microsoft.com/zh-cn/library/ms188012(v=sql.120).aspx
知道了上面這些內容,我們就可以很容易理解怎樣增刪改查登錄賬號了。但一個登錄賬號不是單獨的存在數據庫中,它還關聯了服務權限、數據庫權限等。
數據庫管理
查詢數據庫
數據庫同樣也涉及到增刪改查,首先看看怎樣查詢數據庫。在上一節我們知道數據庫可以從sys.databases目錄視圖中查看,先看看權限系統的數據庫查詢界面,如下圖所示:
通過列表我們能看到數據庫名稱、數據庫所有者、創建時間以及文件路徑。然后我們執行語句:
select * from sys.databases執行結果如下:
分析查詢結果,我們單從sys.databases視圖中是看不到數據庫擁有者的名字以及數據庫文件路徑。但上一節我們講了登錄賬號,我們知道它也有一個sid,所有可以通過sys.databases中的owner_sid和sys.logins關聯。但數據庫文件從哪里查詢?這里又提出了另外一個目錄視圖sys.master_files,它包含了數據庫文件的信息。先執行下面語句:
select * from sys.master_files,https://msdn.microsoft.com/zh-cn/library/ms186782(v=sql.120).aspx
執行結果如下:
從查詢結果可以看出,每個數據庫基本上包含兩行數據。其中,type字段分別為ROWS、LOG,表示數據和日志文件。結果字段中還有一個file_id,它關聯了另外一張數據庫文件視圖sys.database_files。sys.database_files存儲了數據庫文件的詳細信息,包括文件類型、文件大小、文件最大值、文件增長值。執行下面語句:
select * from sys.database_files,視圖說明:https://msdn.microsoft.com/zh-cn/library/ms174397(v=sql.120).aspx
查詢結果如下:
這里有個問題:為什么查詢結果只返回了兩條數據?這是因為我當前選擇的數據是master,sys.database_files只返回當前數據庫的文件信息。現在數據庫信息都知道了.另外,還有一個兼容數據庫視圖sys.sysdatabases(視圖說明:https://msdn.microsoft.com/zh-cn/library/ms179900(v=sql.120).aspx)。它和sys.databases差不多,但能查詢出文件的物理路徑。sys.sysdatabases是sql server 2000中的系統視圖,現在已經不建議使用了。以上幾個數據庫的關聯關系如下:
視圖表已經有了,可直接通過多表關聯查詢出權限管理展示的結果。關聯的查詢語句如下:
select db.name as Name, db.database_id as DbId, db.create_date as CrTime, db.owner_sid as OwnerId, lg.name as OwnerName, mf.physical_name as FileName from sys.databases db left join sys.syslogins lg on db.owner_sid = lg.sid left join sys.master_files mf on db.database_id = mf.database_id and mf.type = 0執行結果如下:
創建數據庫
作為一個開發人員,肯定會經常涉及到創建數據庫。那么怎樣創建數據庫以及創建數據庫需要哪些參數?通過創建登錄賬號(CREATE LOGINS )語句,我們 可以推理創建數據庫也是使用數據定義語句CREATE DATABASE來創建數據。我們先看看權限管理數據庫的查詢界面:
上圖包含了數據庫名稱、數據庫所有者、初始化大小、增長方式、以及文件的最大值。當然,還必須有數據庫文件信息,我直接在后台把文件路徑寫死了,和系統數據庫同目錄。數據庫名稱由我們自己定義,數據庫所有者可通過sys.syslogins查詢選擇,初始值大小由我們自己設置,增長方式包括按照固定值大小或者按照百分比增長、文件最大值包括無限制或者設置最大值、數據庫文件路徑配置為磁盤路徑。
參數已經了解,接下來分析具體的創建語句,我們可以從msdn上查看到完整的數據庫創建語句:
Create a database CREATE DATABASE database_name [ CONTAINMENT = { NONE | PARTIAL } ] [ ON [ PRIMARY ] <filespec> [ ,...n ] [ , <filegroup> [ ,...n ] ] [ LOG ON <filespec> [ ,...n ] ] ] [ COLLATE collation_name ] [ WITH <option> [,...n ] ] [;] <option> ::= { FILESTREAM ( <filestream_option> [,...n ] ) | DEFAULT_FULLTEXT_LANGUAGE = { lcid | language_name | language_alias } | DEFAULT_LANGUAGE = { lcid | language_name | language_alias } | NESTED_TRIGGERS = { OFF | ON } | TRANSFORM_NOISE_WORDS = { OFF | ON} | TWO_DIGIT_YEAR_CUTOFF = <two_digit_year_cutoff> | DB_CHAINING { OFF | ON } | TRUSTWORTHY { OFF | ON } } <filestream_option> ::= { NON_TRANSACTED_ACCESS = { OFF | READ_ONLY | FULL } | DIRECTORY_NAME = 'directory_name' } <filespec> ::= { ( NAME = logical_file_name , FILENAME = { 'os_file_name' | 'filestream_path' } [ , SIZE = size [ KB | MB | GB | TB ] ] [ , MAXSIZE = { max_size [ KB | MB | GB | TB ] | UNLIMITED } ] [ , FILEGROWTH = growth_increment [ KB | MB | GB | TB | % ] ] ) } <filegroup> ::= { FILEGROUP filegroup name [ [ CONTAINS FILESTREAM ] [ DEFAULT ] | CONTAINS MEMORY_OPTIMIZED_DATA ] <filespec> [ ,...n ] } <service_broker_option> ::= { ENABLE_BROKER | NEW_BROKER | ERROR_BROKER_CONVERSATIONS }
具體參數請參考:https://msdn.microsoft.com/zh-cn/library/ms176061(v=sql.120).aspx
現在我們通過權限管理系統創建數據庫,在創建界面輸入數據庫參數,如下圖所示:
點擊“創建”按鈕后, 服務器自動生成數據庫創建SQL語句 ,如下:
USE master; CREATE DATABASE HeaviDb ON( Name = HeaviDb, FILENAME = 'D:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\HeaviDb.mdf', SIZE = 10, FILEGROWTH = 2MB, MAXSIZE = 500)
在創建數據庫時,我們一般要把當前數據庫切換到master數據庫。上面的語句只指定了FILENAME,而沒有指定log的FILENAME,這種情況SQL SERVER會自動在FILENAME同目錄下為我們自動創建HeaviDb_log.ldf文件。SIZE設置為10,這里沒有單位,默認單位為MB,也可以顯示指定KB、MB、GB、TB后綴,例如SIZE = 10MB或者SIZE = 10GB。FILEGROWTH設置為2MB,即數據庫按照2MB自增長,另外我們也可以按照百分比增長,例如FILEGROWTH = 10%。MAXSIZE設置為500,默認單位也是MB。如果我們不限制數據庫文件大小,可直接用UNLIMITED代替MAXSIZE = 500。執行以上SQL語句,我們就能在數據庫中查看到該數據庫了。
修改數據庫
這一節討論怎樣修改數據庫,但這里會涉及到比較核心的知識點。在權限管理系統中,選中數據庫列表某一列,點擊“修改”按鈕,彈出修改數據庫界面。但這里有一個問題,在數據庫列表中只包含了 數據庫名稱、文件以及數據庫所有者信息。而我們修改界面展示了數據庫初始大小以及自增長值。這些信息在列表中是沒有的。但通過數據庫查詢我們知道這些信息保存在sys.master_files中。執行查詢語句:
select mf.database_id as DbId, mf.name as Name, mf.size as InitSize, mf.max_size as MaxSize, mf.growth as Growth, mf.is_percent_growth as IsPercentGrowth from sys.master_files mf where mf.type = 0查詢結果如下:
查詢的數據結果我們不能直接使用,數據庫大小InitSize、數據庫最大值MaxSize、自增長值Growth這些數據不能直接展示在界面,那這些數據到底是什么意思呢?先看看msdn對這幾個字段的描述:
分析幾個字段:
size int 當前文件大小(以 8 KB 為單位的頁數)。 對於數據庫快照來說,size 表示該快照可以一直用於文件的最大空間。 max_size int 最大文件大小(以 8 KB 為單位的頁數):
0 = 不允許增長。
-1 = 文件將一直增長到磁盤充滿為止。
268435456 = 日志文件將增長到最大大小 2 TB。
growth int 0 = 文件大小固定,不會增長。
>0 = 文件將自動增長。
如果 is_percent_growth = 0,則以若干個 8 KB 頁為增量遞增,舍入為 64 KB
如果 is_percent_growth = 1,增量將用整數百分比表示。
is_percent_growth bit 1 = 文件的增長以百分比表示。
0 = 以頁數為單位表示絕對增長大小。
1.size:沒有直接存儲文件大小,而是存儲文件的總頁數,每一頁大小為8KB。以MB為size單位,size的實際值則應該為:(size * 8 /1024)MB;
2. max_size:有三種值,一是等於-1,二是等於0,另一種是大於0 。等於-1表示UNLIMITED(沒有限制)。等於0表示不允許增長。大於0時和size相似,以MB為max_size單位,max_size實際值則應該為:(max_size * 8 /1024)MB;
3.is_percent_growth:值等於0或者1,等於1表示按百分比自增長。等於0表示按固定值增長;
4.growth:等於0表示固定大小,不會自增增長。大於0時依賴於is_percent_growth的值。如果is_percent_growth=0,growth按固定數字自增長。以MB為單位,growth實際值為(growth * 8 /1024)MB。如果is_percent_growth=1,則growth的實際值為growth%;
以上字段了解清楚后,我們的數據庫文件參數就能顯示出來了。例如,修改剛才創建的HeaviDb數據庫,彈出修改界面如下:
修改初始值為20,增長方式為pecent並且值為10,文件最大值沒有限制。這里需要說明幾點:
1.修改的初始值不能小於當前數據庫文件的實際大小;
2.如果文件最大值限制為固定值,那么這個固定值不能小於當前數據庫大小以及修改后的數據庫大小(初始值);
修改參數后界面如下:
點擊“保存”按鈕,后台生成的SQL語句如下:
USE master; ALTER DATABASE HeaviDb MODIFY FILE (Name = HeaviDb,SIZE = 20,FILEGROWTH = 20,MAXSIZE = UNLIMITED)
修改數據庫使用DDL的ALTER DATABASE語句,修改文件使用MODIFY FILE語句。完整的數據庫修改SQL請查看:
https://msdn.microsoft.com/zh-cn/library/ms174269(v=sql.120).aspx。
刪除數據庫
數據庫的刪除語句比較簡單,SQL與語句如下:
USE master; DROP DATABASE HeaviDb
刪除數據庫必須知道:系統數據庫是不能刪除的;不能刪除正在使用的數據庫。
總結
本篇隨筆主要介紹了登錄賬號的查詢、創建、修改、刪除,以及數據庫的查詢、創建、修改、刪除所涉及的系統視圖以及DDL語句。通過這篇內容我們能夠比較清楚的了解登錄賬號以及數據庫在SQL SERVER中的存儲元數據結構。本篇的內容都是一些基礎知識,但同時也是比較重要的基礎知識。下一篇將會詳細分析數據庫中登錄賬號和數據庫的權限設置。
附錄
如果本篇內容對大家有幫助,請關注博主。如果覺得不好,也歡迎拍磚。你們的反饋就是博主的動力!下篇內容,敬請期待!


![clipboard[1] clipboard[1]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNDM1NDItNDkwMzc3NjM5LnBuZw==.png)
![clipboard[2] clipboard[2]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNDQ0NjQtNjMzNzAyMjI5LnBuZw==.png)
![clipboard[4] clipboard[4]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNDc1NDItNDIyNDA1MDA5LnBuZw==.png)
![clipboard[5] clipboard[5]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNDkxMjAtNzU5NzkzMTcxLnBuZw==.png)
![clipboard[6] clipboard[6]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTA0NzktMjg4OTc0Njk3LnBuZw==.png)
![clipboard[7] clipboard[7]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTIyNzYtNDE3MzUyODkyLnBuZw==.png)
![clipboard[8] clipboard[8]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTM4MjMtMTY2NTMyOTU3NS5wbmc=.png)
![clipboard[9] clipboard[9]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTQ3NDUtMTI2MzIzODIzMS5wbmc=.png)
![clipboard[10] clipboard[10]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTU5MDEtNDU2ODAzOTQyLnBuZw==.png)
![clipboard[11] clipboard[11]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTcyMTQtMTkxNTEzNTczLnBuZw==.png)
![clipboard[12] clipboard[12]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTc5OTUtMTAwNjkxNzAyMy5wbmc=.png)
![clipboard[13] clipboard[13]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTg5NzktMTIyOTIwNjU2OC5wbmc=.png)
![clipboard[14] clipboard[14]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIwNTk5MTctNzgwMzE4NDcucG5n.png)
![clipboard[15] clipboard[15]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIxMDA3NzYtOTcxNTA5MzE3LnBuZw==.png)
![clipboard[16] clipboard[16]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIxMDE3MjktMTY2NDgxODUxMC5wbmc=.png)
![clipboard[17] clipboard[17]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIxMDM2MjAtODYzNDg1NzA4LnBuZw==.png)
![clipboard[18] clipboard[18]](/image/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvMzgwMjgxLzIwMTUxMi8zODAyODEtMjAxNTEyMjkwMjIxMDQ4ODUtMTc2Mjk3Mzk5My5wbmc=.png)