存储过程,sysname和quotname()

时间:2012-04-23 05:26:07

标签: sql sql-server

这是新的......

提供程序(我假设它是他们的代码)已经设置了一个存储过程来修改用户的SQL服务器密码。他们使用了sysname类型来传递信息:OLD,NEW和LOGINAME。

当他们执行更改密码的命令时,他们使用quotename()括起传递给函数的文本。

在此之前,在检查用户名是否存在时,他们会在没有任何格式控制的情况下传递LOGINAME。

这在过去并不是问题,但由于我们最近将用户名政策从初始+姓氏(FSURNAME)更改为名字(点)姓氏(FIRST.SURNAME),因此例程崩溃了。我认为这是因为在传递给see-if-they-exist函数时,缺少对该用户名的样式控制。

代码:

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] )手动执行时,它当然可以正常工作。

1 个答案:

答案 0 :(得分:0)

这是由于Sql Server如何处理sysname类型的参数值。考虑一下。

public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }

我仍然在寻找一些好的解释。