【问题标题】:Insert data in dynamic column specified by user在用户指定的动态列中插入数据
【发布时间】:2015-01-23 06:18:57
【问题描述】:

我有包含isactivehindienglish、...列的语言表。

我正在创建一个用于插入新数据的存储过程,如下所示:

create proc USP_Insertdata
   @lang varchar(20),
   @data nvarchar(50)
as
begin
   EXEC(N'insert into language(@lang, isactive) values(@data, 'true')') 
end

在执行中遇到问题

【问题讨论】:

  • @lang 是可变的,我认为这会导致您出现问题。一种解决方法可以是 Switch 机箱。在 CASE 中为每种语言编写不同的查询,并根据用户的输入应用切换。
  • 这里不需要动态SQL。只需创建一个 IF .. ELSE 分支。通过为每种语言指定不同的列名。
  • @VishalGajjar:说真的?如果您必须支持more than a couple cultures,您将拥有一棵巨大的IF .. ELSE 树。如果我无法更改数据库设计,动态 SQL 绝对是我在这种情况下的首选。

标签: sql sql-server


【解决方案1】:

您需要动态绑定lang,因为无法对列名进行参数化,但是,可以使用sp_executesql@data 进行参数化:

create proc USP_Insertdata @lang varchar(20), @data nvarchar(50)
as 
begin
   declare @sql NVARCHAR(MAX) = N'insert into language(' + @lang + ',isactive) values(@data,''true'')';
   exec sp_executesql  @sql, N'@data nvarchar(50)', @data=@data
end

Sql Fiddle here。请注意下面关于验证列名 (@lang) 是否是表中的有效列的 cmets,以防止像 Sql Injection 这样的恶意行为。鉴于必须有有限数量的列名,我建议根据白名单验证 @lang(即根据允许的值列表检查 @lang

编辑
诉诸动态 Sql 通常是一种异味。我不同意表的设计,因为使用上述proc插入数据后,这将导致稀疏数据类似于:

语言

English    French    Russian  IsAcive
Yes        NULL      NULL     true
NULL       Oui       NULL     true
NULL       NULL      Da       true

作为替代方案,您可以选择将语言取消透视为列,而是在首先创建可用语言的简单参考表之后将 data 插入规范化为语言:

语言类型

ID(PK) Language
EN     English
FR     French
RU     Russian

查找适当的语言代码后,原始Language 表将被规范化为:

语言数据

LanguageId(FK) Data     IsActive
EN             Yes      1
FR             Oui      1
RU             Da       1

最后一点 - isactive 似乎暗示了一个布尔值 - 更常见的是将此建模为 BIT or CHAR enumeration

【讨论】:

  • 嗨@StuartLC我也建议QUOTENAME(@lang),或者sp_ExcuteSQL是否处理注入?
  • @VishalGajjar 你是对的 - 它只会处理参数化变量的注入,即@data 是安全的,但@lang 不是。由于列数是有限的,因此在执行此操作之前,我会根据可能列的白名单验证这些列。
  • 谢谢我会采取同样的预防措施:)
【解决方案2】:

使用此程序。

    create proc USP_Insertdata @lang varchar(20), @data nvarchar(50) as begin

EXEC(N'insert into language(' + @lang + ',isactive) values(' + @data + ',true)') end

【讨论】:

  • "@lang" 将导致此处,OP 正在尝试传递列名
  • @lang 容易被注入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
相关资源
最近更新 更多