SQL Server存储过程选择由参数传递的特定列,并检查其他约束

时间:2018-10-31 19:29:06

标签: sql sql-server

我想在SQL Server 2017中创建一个存储过程并让它在其他地方调用(即Python)。它接受三个参数,stkname-库存名称,stktype-库存类型,colname-输出列(仅返回这些列)。 @colnamevarchar,用于存储所有必需的列名,用,分隔。

  • 如果未指定@colname,则返回所有列(*
  • 如果未指定stknamestktype,请不要对其进行过滤

到目前为止,这是我的代码:

create procedure demo 
     (@stkname varchar(max), 
      @colname varchar(max), 
      @stktype varchar(max)) 
as
begin
    ----These lines are pseudo code -----
    select 
        (if @colname is not null, @colname, else *) 
    from 
        Datatable 
    (if @stkname is not null, where stkname = @stkname)
    (if @stktype is not null, where stktype = @stktype)

    ---- pseudo code end here-----
end

所需的结果是

exec demo @colname= 'ticker,price', @stktype = 'A'

对于stktype ='A'的所有记录返回两列-报价器和价格。

我可以想象有可能使用“动态SQL”,但不能做到“优雅”,我需要编写2 * 2 * 2 = 8种情况。

我该如何更好地实现它?

PS:这个问题不是重复的,因为不仅我需要传递列名,而且还需要“通过其他参数生成查询”

1 个答案:

答案 0 :(得分:4)

您需要动态SQL,但是您无需为每个排列编写一个案例,并且防止恶意行为的确不是那么困难。

find

目前尚不清楚teeCREATE PROCEDURE dbo.demo -- always use schema prefix @stkname varchar(max) = NULL, @colnames nvarchar(max) = NULL, -- always use Unicode and use a proper name @stktype varchar(max) = NULL AS BEGIN DECLARE @sql nvarchar(max); SELECT @sql = N'SELECT ' + STRING_AGG(QUOTENAME(LTRIM(RTRIM(x.value))), ',') FROM STRING_SPLIT(@colnames, ',') AS x WHERE EXISTS ( SELECT 1 FROM sys.columns AS c WHERE LTRIM(RTRIM(x.value)) = c.name AND c.[object_id] = OBJECT_ID(N'dbo.DataTable') ); SET @sql += N' FROM dbo.DataTable WHERE 1 = 1' + CASE WHEN @stkname IS NOT NULL THEN N' AND stkname = @stkname' ELSE N'' END + CASE WHEN @stktype IS NOT NULL THEN N' AND stktype = @stktype' ELSE N'' END; EXEC sys.sp_executesql @sql, N'@stkname varchar(max), @stktype varchar(max)', @stkname, @stktype; END 列是否真的是stkname,我对此表示怀疑,您应该将这些声明替换为与列定义匹配的实际数据类型。在任何情况下,使用这种方法,用户都无法将废话传递到列列表中,除非他们以某种方式能够向该表中添加与其废话模式相匹配的列(以及为什么他们仍然键入此内容而不是选择列从已定义的列表中?)。而且,它们作为字符串传递给其他两个参数的任何数据都无法在此处执行。您担心的事情可能是草率代码的结果,您不小心附加了用户输入并未经检查就执行了它,就像这样:

stktype

有关恶意行为的更多信息,请参见: