以列名作为输入参数的存储过程中的动态 sql

Posted

技术标签:

【中文标题】以列名作为输入参数的存储过程中的动态 sql【英文标题】:dynamic sql in stored procedure with column name as input parameter 【发布时间】:2014-03-11 17:28:07 【问题描述】:

我有这个存储过程,它接受一个 comlumn 名称作为 inptu 参数。 SELECT语句会根据输入参数选择一列

create procedure getColumn (@whichColumn varchar)
as
begin
    declare @sql nvarchar(max) 
    set @sql = 'SELECT [' + @whichColumn + ']' 
        + ' FROM myTable'
        + ' where ['+ @whichColumn + '] is not null'
        + ' and [' + @whichColumn + '] != '''' ' ;
    exec sp_executesql @sql
end

当我执行这个存储过程时,

exec getColumn 'Apple';

错误提示“无效的列名'A'”。 我不明白为什么它只获取输入的第一个字符

【问题讨论】:

【参考方案1】:

查看您的参数声明:

@whichColumn varchar

From MSDN:

当 n 未在数据定义或变量声明中指定时 语句,默认长度为1。

所以这是一个单字母varchar。尝试指定大小:

@whichColumn varchar(50)

或者更好的是,使用系统定义的类型作为对象名称:

@whichColumn sysname

【讨论】:

^^^^这是你的答案。始终声明列的长度。 如果没有提到长度,我以为是 30 :S @M.Ali:如果你省略了castconvert 中的长度,那是真的。但在变量声明中,默认长度为 1。你可以vote here来解决这个疯狂问题。 opss 搞混了。 :) 我试过投票,但它不会让我稍后再试。 /sigh 这不是公认的答案这一事实令人不安。【参考方案2】:
create procedure getColumn (@whichColumn nvarchar(128))   --<-- Maximum column name lenght
as
begin
    declare @sql nvarchar(max); 
    set @sql =   N'SELECT ' + QUOTENAME(@whichColumn)+ N' FROM myTable'
               + N' where '+ QUOTENAME(@whichColumn) + N' is not null'
               + N' and ' + QUOTENAME(@whichColumn)  +  N' != '''' ' ;
    exec sp_executesql @sql
end

附带说明 在连接字符串中使用方括号与使用 QUOTENAME 函数不同。

【讨论】:

您是否愿意对投反对票的人发表评论? +1 失去平衡。也不知道你为什么拿到 DV。 干杯 Zane 有一些 numties 反对投票来取乐。我希望有一个系统,每次有人不公平地投票时,他们的声誉都会-100:S M.阿里在阅读您建议的答案之前,我不知道 TSQL 关键字 QUOTENAME。它解决了我在编写动态 SQL 以在 UPDATE 存储过程中设置列名的问题。一个好处是编写和理解恕我直言更干净。【参考方案3】:

改变这一行

create procedure getClumn (@whichColumn varchar)

create procedure getClumn (@whichColumn varchar(max))

因为如果你当时没有分配 varchar 的大小,它只考虑一个字符,所以它只得到一个字符 A 并产生错误。

【讨论】:

哇,我们不要得意忘形,一路走到VARCHAR(MAX),我的假设是他可能需要不到 8,000 个字符来完成这项工作。 @Zane 我的假设是他永远不需要超过 128 :)

以上是关于以列名作为输入参数的存储过程中的动态 sql的主要内容,如果未能解决你的问题,请参考以下文章

SP_EXECUTESQL 中的 SQL 注入

使用 Oracle 表作为输入参数编写 Oracle 存储过程

SQL注入求指点

SQL Server存储过程中使用表值作为输入参数示例

pl/sql 存储过程:参数名与列名相同

sqlserver 存储过程调用报错