在存储过程的动态SQL中使用变量

问题描述 投票:0回答:1
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) 

[请帮助我解决此问题。

代码:

BEGIN
    -- Create a view as view doesnt exisit
    SET @Sql = 'create view ' + @First3Digits 
    + ' as 
    (select SubjectName from dbo.Subjects where SubjectName like '+@First3Digits+'%'+');';
    Execute sp_executesql @Sql, N'@First3Digits nvarchar(3)', @First3Digits= @First3Digits, @First3Digits=@First3Digits;
    SET @Result = 0;
END

编辑:我的下一个问题

执行代码:

EXEC [dbo].[Create_Subjects] '1234567890'                                                               
Issue Encountered:
Msg 156, Level 15, State 1, Line 28
Incorrect syntax near the keyword 'view'.
Msg 102, Level 15, State 1, Line 29
Incorrect syntax near ')'.

请让我知道如何解决此问题

sql-server tsql dynamic-sql
1个回答
1
投票

行:

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

被破坏是因为@First3Digits是表的名称(我想-尽管它只有nvarchar(3)!),并且不能像这样直接在查询中使用,而是需要使用动态SQL,特别是sp_executesql如下:

sp_executesql

请注意使用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'@Subj_ID nvarchar(9), @Result bit out', @Subj_ID = @Subj_ID, @Result = @Result out; -- @Result is now set as required 来防止SQL注入。

顺便说一句,从表面上看,您的设计看起来非常需要改进。根据quotename创建视图(无论实际情况如何)似乎都是有缺陷的,容易产生维护问题和可伸缩性问题。可能有更好的方法。

© www.soinside.com 2019 - 2024. All rights reserved.