核心概念
- 登錄名:實例級,僅授予「連接 SQL Server」權限
- 用戶名:數據庫級,授予「訪問該數據庫對象」權限
- 映射:一個登錄名可映射多個數據庫的不同用戶名,但在同一數據庫只能映射一個用戶名
dbo 的特殊身份
sa 登錄(SQL 認證)或 Windows 管理員登錄(Windows 認證)進入數據庫時,對應用戶名為 dbo
- dbo 是數據庫擁有者,擁有該數據庫所有權限,無需額外授權
- 普通登錄
me 映射用戶 me,創建對象所有者為 me(如 me.testtable),而非 dbo
為什麼要加所有者前綴?
不同用戶可創建同名對象(如 me.testtable 和 you.testtable),結構數據可能完全不同。調用時必須限定所有者避免歧義:
SELECT * FROM you.testtable;
跨用戶訪問對象的兩個條件
- 當前用戶具有 db_owner 角色(企業管理器 → 用戶屬性 → 角色勾選)
- 查詢時顯式指定所有者:
SELECT * FROM dbo.ufn_GetName();
dbo 作為管理員天然滿足條件 1,可直接訪問任何用戶對象。
省略所有者時的解析順序
具有 db_owner 的用戶執行 SELECT * FROM testtable:
- 先找當前用戶同名對象(
me.testtable)
- 找不到則找
dbo.testtable
- 仍無則報錯
函數調用的強制規則
- 返回表值的函數可省略所有者
- 標量函數、多語句函數必須加所有者:
dbo.fn_CalcTax()
比喻:大樓與房間
- SQL Server = 大樓
- 登錄名 = 進大樓的鑰匙
- 數據庫 = 房間
- 用戶名 = 進房間的鑰匙
- 一把大樓鑰匙(登錄名)可配多把房間鑰匙(多數據庫用戶名)
最佳實踐
- 生產環境始終在代碼中顯式指定架構前綴(
dbo. 或業務架構名),避免解析開銷與歧義
- 應用使用專用登錄名+用戶名(非 sa/dbo),最小權限原則
- 跨架構訪問時,授予
db_owner 或具體 SELECT/EXECUTE 權限於目標架構
- 避免直接用 sa 登錄運行應用,違規操作無法審計