2008年12月22日 星期一

帳號提升權限,原來的程式反而出現錯誤了?

先說明當時情況好了,接到一個任務,要重建一個系統的開發環境,SQL Server要獨立一台,因為需要複製二十多個資料庫,只要資料庫結構,不要資料,想說只是給測試用的,為了省時,我把新的開發環境程式用的連線帳號,權限提升到最大sysadmin,這樣權限設定就簡單許多了,結果反而程式不能跑了說,會有錯誤,而且是很簡單T-SQL喔

Select * from table2

上面這個簡單到不能在簡單了,有table2,而且使用的連線帳號已經給到sysadmin,居然會有錯誤,在原本的機器上可以跑,為什新的不行,我當時想破頭,不知為什,甚至懷疑是不是SQL版本不同造成,結果後來終於研究出來,原來是沒使用"物件擁有者.物件"所造成的,各位看看我以下的T-SQL,COPY過去使用,配合註解的說明,應該可以了解到問題在哪?

--先用系統管理員角色登入,此例為join
--假設在Northwind下有一使用者t,角色為db_owner
use northwind

--尋找目前使用者的名稱與使用者的登入識別名稱
select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
--join dbo

--建立一個owner為t的表格t1
create table t.t1(a1 int)

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 無效的物件名稱 't1' */
/*不使用全名,會先找"使用者名稱.物件",再找"dbo.物件"
兩個結果都是"dbo.物件",因為沒有dbo.t1,所以會回傳錯誤囉*/

--模擬使用者t,角色為db_owner
setuser 't'
select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
-- t t

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 正常 */
/*因為會先找"使用者名稱.物件",這個情況就會找t.t1囉,所以有找到*/

--設回原來使用者
setuser

--把t新增到 sysadmin 伺服器的固定角色內
EXEC sp_addsrvrolemember 't', 'sysadmin'

--模擬使用者t
setuser 't'

select suser_sname() as '登入識別名稱' , user_name() as '目前使用者的名稱'
/* t dbo */
/*注意使用者名稱原來是t,現已變成dbo囉,因為已是sysadmin成員之一*/

--使用全名
select * from t.t1
/* 正常 */
--不使用全名
select * from t1
/* 無效的物件名稱 't1'。 */
/*因為會先找"使用者名稱.物件",此時使用者名稱已變為dbo,
所以這個情況就會找dbo.t1囉,問題是沒有押,再找第二次也是dbo.t1,
還是沒有,所以回報錯誤囉*/

--設回原來使用者
setuser






因為table2的擁有者不是dbo,如果擁有者是dbo,一般是不需要使用 ObjectOwner.DatabaseObject 語法的;如果擁有者不是dbo,最好使用ObjectOwner.DatabaseObject 語法囉


個人覺得不管什麼情況,還是使用ObjectOwner.DatabaseObject 語法比較妥當,效率也會好點

0 意見:

張貼留言