【问题标题】:Use variable in dynamic SQL在动态 SQL 中使用变量
【发布时间】:2020-05-07 19:36:43
【问题描述】:
ALTER PROCEDURE [dbo].[Create_Subjects]
    @Subj_ID nvarchar(9)
AS
    DECLARE @First3Digits nvarchar(3);
    DECLARE @Result int;

    -- Fetching the first 3 digits of the subject
    SET @First3Digits = SUBSTRING(@Subj_ID,1,3);

    -- Check if view is present or not
    IF EXISTS (SELECT 1 FROM sys.views WHERE Name = @First3Digits)
    BEGIN
        PRINT 'View exists'
        -- checking if the subject is present in the view
        IF EXISTS (SELECT 1 FROM @First3Digits WHERE SubjectName = @Subj_ID)
        BEGIN
            SET @Result = 1;
        END
        ELSE
        BEGIN
            SET @Result = 0;
        END
    END
    ELSE
    BEGIN
        -- Create a view as view doesn't exist
        EXEC('create view' + @First3Digits 
            + 'as 
                    (select SubjectName from dbo.Subjects where SubjectName like '+@First3Digits+'%'+');')

        SET @Result = 0;
        PRINT 'view does not exist'
    END

    PRINT @First3Digits
GO;

在上面的代码中,我遇到了问题

IF EXISTS (SELECT 1 FROM @First3Digits WHERE SubjectName = @Subj_ID) 

请帮我解决这个问题。

【问题讨论】:

  • 如果你打算写动态sql,那么你需要看看你生成的语句。这样做,你会发现一个问题。
  • 由于@First3Digits 不是表变量,但可能 包含表的名称,因此您需要将问题陈述设为动态SQL。尽管使用的三个字符似乎排除了太多乐趣,但在深入了解动态 SQL 兔子洞之前,请参阅 SQL Injection

标签: sql-server tsql dynamic-sql


【解决方案1】:

行:

IF EXISTS (SELECT 1 FROM @First3Digits WHERE SubjectName = @Subj_ID)

因为@First3Digits 是表的名称而损坏(我假设-即使它只有nvarchar(3)!)并且不能直接在这样的查询中使用,而是您需要使用动态SQL,特别是@987654321 @如下:

PRINT 'View exists'

declare @Sql nvarchar(max);

set @Sql = 'select @Result = case when exists (select 1 from dbo.' + quotename(@First3Digits) + ' where SubjectName = ''' + @Subj_ID + ''') then 1 else 0 end';

execute sp_executesql @Sql, N'@Result bit out', @Result = @Result out; 

-- @Result is now set as required

注意使用quotename 来防止SQL 注入。

顺便说一句,从表面上看,您的设计看起来非常需要改进。根据Subject(无论实际是什么)创建一个视图似乎存在缺陷,容易出现维护问题和可伸缩性问题。可能有更好的方法。

【讨论】:

  • 奇怪的是,你将@sql... ' where SubjectName = ''' + @Subj_ID + ''') ... 组装起来,然后将@Subj_ID 作为参数传递,尽管在动态SQL 语句中没有引用它。是否允许将其用于 SQL 注入?
  • @HABO 很好奇 :) - 没有给予足够的关注 :) 现已删除。
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 2012-12-11
  • 2011-06-05
  • 1970-01-01
相关资源
最近更新 更多