如果事先不知道列名而没有动态sql,如何更新sql列

时间:2011-11-28 01:56:18

标签: sql-server sql

SQl Server 2008

示例:

在页面上

编辑用户配置文件设置,如DOB,性别,名称等...,我不知道用户希望我更新哪些列。我是否应该将所有这些值传递给存储过程,并更新所有配置文件列值,即使用户可能只更改了其中的一个或两个?看起来有点不好,是吗?

出于安全考虑,使用动态sql不是一种选择。

4 个答案:

答案 0 :(得分:1)

您可以使用一种模式,其中您的所有字段都是存储过程的参数,并且参数的默认值是字段外的字节值(分别)。然后你写一个更新语句,如:

update table
set 
   age = case when @age = -1 then age else @age end,
   weight = case when @weight = -1 then weight else @weight end,
   ...

您可以使用字段作为参数和一个额外的位域参数来完成类似的操作,该参数将指定给定列是否已更新。这将是这样的:

update table
set 
   age = case when @updated & 0x01 then @age else age end,
   weight = case when @updated = 0x02 then @weight else weight end,
   ...

他们都有自己的优点和缺点。

答案 1 :(得分:0)

没有办法根据类似的列号更新表。您必须使用动态SQL来执行此操作。如果使用参数化查询,无空登录用户,执行as和sp_executesql正确完成风险可以删除。

答案 2 :(得分:0)

我并不认为这很重要。如果您需要编写存储过程来更新任何一列,那么更新一列或所有列并不重要。如果你通过编写几列信息而不是一条信息来面对重大的性能影响,我会感到惊讶。

如果您担心不必要地更新数据(即,什么都没有真正改变,但用户仍然点击了保存),并且可能会弄乱审计触发器等,那么请查看检测用户是否实际修改了表单上的值的方法与通过将数据标记为脏的最初从数据库中读取的内容进行比较

答案 3 :(得分:0)

创建一个默认参数设置为null的存储过程。然后只提供您想要更改的参数。在update语句中,检查此值为Age = isnull(@Age, Age)的空值。

请参阅以下示例:

-- sample table
    create table UserProfile
    (
        ID int identity(1,1),
        UserName nvarchar(10),
        Gender char(1),
        Age int
    )

    insert into UserProfile values('Bob', 'M', 19)
    insert into UserProfile values('June', 'F', 23)

-- stored proc    
    create proc UpdateUser
    ( 
        @ID int,
        @UserName nvarchar(10) = null,
        @Gender char(1) = null,
        @Age int = null
    )
    as
    begin
        update UserProfile set
            UserName = isnull(@UserName, UserName),
            Gender = isnull(@Gender, Gender),
            Age = isnull(@Age, Age) 
        where ID = @ID
    end

-- usage:    
    exec UpdateUser @ID=1, @Age=29
    exec UpdateUser @ID=1, @UserName='Bill'
    exec UpdateUser @ID=2, @UserName='Julie', @Age=24
    exec UpdateUser @ID=2, @UserName='Mitch', @Gender='M', @Age=56

    select * from UserProfile