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)
[请帮助我解决此问题。
行:
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'@Result bit out', @Result = @Result out;
-- @Result is now set as required
来防止SQL注入。
顺便说一句,从表面上看,您的设计看起来非常需要改进。根据quotename
创建视图(无论实际情况如何)似乎都是有缺陷的,容易产生维护问题和可伸缩性问题。可能有更好的方法。