【问题标题】:Using an SQL Parameter for the column name in the WHERE clause在 WHERE 子句中为列名使用 SQL 参数
【发布时间】:2015-11-10 03:25:21
【问题描述】:

我正在使用 SQL 参数来允许用户使用视图中的下拉菜单创建自己的 SELECT 查询。参数值使用 MVC 控制器中的实体框架从视图传递到存储过程。 SQL 参数不能直接用于列名,所以我决定使用 case 语句。问题是没有数据被返回,所以他们在我使用语句的方式上一定有一些错误。

    @topLeftInput varchar(100),
    @topRightInput varchar(100)
AS
BEGIN
        Select  * from test
            where 
                CASE @topRightInput 
                    WHEN 'BasicReturnReasonId' THEN BasicReturnReasonId
                    WHEN 'ClientName' THEN ClientName
                    WHEN 'CreditDeniedReasonId' THEN CreditDeniedReasonId
                    WHEN 'ItemsnotReturnedReasonId' THEN ItemsnotReturnedReasonId
                    WHEN 'ManufacturerId' THEN ManufacturerId
                    WHEN 'ManufacturerOrderNumber' THEN ManufacturerOrderNumber
                    WHEN 'ProductConditionId' THEN ProductConditionId
                                ELSE NULL
                    END
                = @topRightInput;
END

输入的值分别是“ProductConditionId”和“3”。

当我对整个查询使用 if 语句时,我确实有这个工作,但它有点矫枉过正而且太长了(看起来不像,因为我为了一个例子而把它删掉了)。

这是我为第一个选项所做的示例:

if @topLeftInput = 'BasicReturnReasonId'
    Begin
        Select * from test
            where BasicReturnReasonId = @topRightInput;
    End

我怎样才能使这个与 case 语句一起工作?

谢谢!

【问题讨论】:

  • 实际上,刚刚意识到这只是一个错字,应该关闭。 @topRightInput 应该是 @topLeftInput。进行更改时工作正常。还早,我只是错过了:/
  • 这里有一个小技巧,以后可能会对你有很大帮助。经常(但显然并非总是如此)。最好声明一个局部变量,将其定义为输入参数的值,然后在查询中使用局部变量。直接使用输入参数可能会导致重新编译问题,我发现该问题会使存储过程的速度降低几个数量级。
  • 好的,谢谢提示

标签: sql sql-server asp.net-mvc sql-server-2008 switch-statement


【解决方案1】:

一个你可以使用的简单技巧:

DECLARE @QUERY as varchar(max);
SET @QUERY='Select  * from test where '+ @topLeftInput +' = '+@topRightInput + ' ;'
EXEC(@QUERY)

注意:这种方法容易受到sql注入的影响。因此,请确保使用正确的验证。

【讨论】:

  • 警告这容易受到 sql-injection 的攻击。
【解决方案2】:
CREATE PROCEDURE myProc
    @topLeftInput varchar(100),
    @topRightInput varchar(100)
AS
BEGIN
  DECLARE @sql NVARCHAR(MAX);

SET @sql = N'Select  * from test
             where ' + 
            CASE @topLeftInput 
                WHEN 'BasicReturnReasonId'      THEN QUOTENAME(N'BasicReturnReasonId')
                WHEN 'ClientName'               THEN QUOTENAME(N'ClientName')
                WHEN 'CreditDeniedReasonId'     THEN QUOTENAME(N'CreditDeniedReasonId')
                WHEN 'ItemsnotReturnedReasonId' THEN QUOTENAME(N'ItemsnotReturnedReasonId')
                WHEN 'ManufacturerId'           THEN QUOTENAME(N'ManufacturerId')
                WHEN 'ManufacturerOrderNumber'  THEN QUOTENAME(N'ManufacturerOrderNumber')
                WHEN 'ProductConditionId'       THEN QUOTENAME(N'ProductConditionId')
            END
          + N' = @topRightInput;'

exec sp_executesql @sql
                  ,N'@topRightInput varchar(100)'
                  ,@topRightInput

END

如果参数@topLeftInput具有列名的确切值,那么它就更简单了

CREATE PROCEDURE myProc
    @topLeftInput varchar(100),
    @topRightInput varchar(100)
AS
BEGIN
  DECLARE @sql NVARCHAR(MAX);

SET @sql = N'Select  * from test
             where ' +  QUOTENAME(@topLeftInput)  + N' = @topRightInput;'

exec sp_executesql @sql
                  ,N'@topRightInput varchar(100)'
                  ,@topRightInput

END

【讨论】:

    猜你喜欢
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多