2012-04-23 55 views
0

新在這個...存儲過程,主機名與quotname()

提供者(我認爲這是他們的代碼)已經成立了一個存儲過程來修改用戶的SQL服務器密碼。他們使用sysname類型來傳遞信息:OLD,NEW和LOGINAME。

當他們執行命令更改密碼時,他們使用quotename()括起傳遞給該函數的文本。

在此之前,在檢查用戶名是否存在的同時,他們通過LOGINAME而不進行任何格式控制。

這在過去一直沒有問題,但是由於我們最近將我們的用戶名策略從初始名+(姓氏)(FSURNAME)更改爲名(名)姓(FIRST.SURNAME),因此例程崩潰了。我認爲這是因爲在傳遞給see-if-they-exist函數時缺乏對用戶名的quotename()風格控制。

代碼:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER procedure [sys].[sp_password] 
    @old sysname = NULL,  -- the old (current) password 
    @new sysname,    -- the new password 
    @loginame sysname = NULL -- user to change password on 
as 
-- SETUP RUNTIME OPTIONS/DECLARE VARIABLES -- 
set nocount on 
declare @exec_stmt nvarchar(4000) 

-- RESOLVE LOGIN NAME 
if @loginame is null 
    select @loginame = suser_sname() 

if @new is null 
    select @new = '' 

-- DISALLOW USER TRANSACTION -- 
set implicit_transactions off 
IF (@@trancount > 0) 
begin 
    raiserror(15002,-1,-1,'sys.sp_password') 
    return (1) 
end 

-- CHECK IT'S A SQL LOGIN -- 
if not exists (select * from master.dbo.syslogins where 
       loginname = @loginame and isntname = 0) 
begin 
    raiserror(15007,-1,-1,@loginame) 
    return (1) 
end 

if @old is null 
    set @exec_stmt = 'alter login ' + quotename(@loginame) + 
     ' with password = ' + quotename(@new, '''') 
else 
    set @exec_stmt = 'alter login ' + quotename(@loginame) + 
     ' with password = ' + quotename(@new, '''') + ' old_password = ' + quotename(@old, '''') 

exec (@exec_stmt) 

if @@error <> 0 
    return (1) 

-- RETURN SUCCESS -- 
return (0) -- sp_password 

我強烈懷疑,這裏的代碼:

if not exists (select * from master.dbo.syslogins where 
       loginname = @loginame and isntname = 0) 

原因造成的問題,因爲,據我所知,代碼FIRST.LAST傳遞給常規檢查,然後將其解釋爲一個對象而不是文本。

是否可以做同樣的事情,但強迫發送文本?類似於代碼中其他地方使用的quotename()函數?


編輯:

執行該存儲過程調用:sp_password的NULL,ABCDEFGH,FIRST.LAST

錯誤接收的:消息102,級別15,狀態1,第1行'。'附近的語法錯誤。

當通過添加括號手動執行(sp_password的NULL,ABCDEFGH,[FIRST.LAST])它當然完美。

+0

你會得到什麼錯誤?您是否將新用戶添加到SQL Server?使用SSMS並查看「對象資源管理器 - 安全 - 登錄」。如果用戶不在那裏,那麼密碼更改將失敗,並且「FIRST.SURNAME」不是有效的登錄名或者您沒有權限。 – 2012-04-23 05:47:49

+0

您不應該引用查找對象的名稱。 'loginname = @ loginame'是正確的。而且他們在動態SQL中引用的方式似乎是正確的。那麼你看到的錯誤究竟是什麼? – 2012-04-23 06:16:18

+0

編輯原創問題。 – Lindsay 2012-04-23 23:26:48

回答

0

這是由於Sql Server如何處理類型爲sysname的參數值。考慮這一點。

create procedure TakeSysname 
    @Sysname sysname 
as 
    --does nothing; 
go 

--This works. 
exec TakeSysname JohnDoe; 
print N'Worked'; 
go 

--This works. 
exec TakeSysname 'John.Doe'; 
print N'Worked' 
go 

--This does not. 
exec TakeSysname John.Doe; 
print N'Worked'; 
go 

雖然我仍然在尋找一些很好的解釋。