从 SP 获取列名作为参数,并在过程中为该列设置一个值
Get the column name as a parameter from SP and set a value to that Column with in the procedure
ALTER proc [dbo].[sp_dosomethingwithStudentAttn] @AttnList as dbo.StudentAttendanceList readonly,@DeptId int,@SemId int,@SecId int,@DayId int,@currentDate date,@period nvarchar(5)
as
declare @IfStudentDayWiseAttnExists as bit,
@updateQuery as varchar(max),
@insertQuery as varchar(max)
begin
set nocount on
declare
@stnId as int,
@stnAttnStatus as nvarchar
declare cur_UpdateInsertStnAttnData cursor forward_only static for
select StudentId,AttdnStatus from @AttnList
open cur_UpdateInsertStnAttnData
if @@CURSOR_ROWS>0
begin
fetch next from cur_UpdateInsertStnAttnData into @stnId,@stnAttnStatus
while @@FETCH_STATUS=0
begin
set @IfStudentDayWiseAttnExists=(select case when exists
(
select * from tbl_DailyAttend
where DeptId=@DeptId and
SemId=@SemId and
SecId=@SecId and
attDate=@currentDate and
StuId=@stnId
)
then CAST(1 AS bit)
else CAST(0 as bit)
end
)
if @IfStudentDayWiseAttnExists='true'
begin
if @stnAttnStatus='true'
begin
select @updateQuery='update tbl_DailyAttend set '+@period+'=''true'' where DeptId='+@DeptId+' and SemId='+@SemId+' and SecId='+@SecId+' and attDate='+CONVERT(date, @currentDate)+' and StuId='+@stnId+''
EXEC (@updateQuery)
end
else
begin
select @updateQuery='update tbl_DailyAttend set '+@period+'=''false'' where DeptId='+@DeptId+' and SemId='+@SemId+' and SecId='+@SecId+' and attDate='+CONVERT(date, @currentDate)+' and StuId='+@stnId+''
EXEC (@updateQuery)
end
end
else
begin
set @insertQuery='insert into tbl_DailyAttend (DeptId,SemId,SecId,DayId,attDate,'+@period+') values ('+@DeptId+','+@SemId+','+@SecId+','+@DayId+','+@currentDate+','+@stnAttnStatus+')'
end
fetch next from cur_UpdateInsertStnAttnData into @stnId,@stnAttnStatus
end
end
end
由于您正在构建动态 Sql,因此您需要将语句构建为字符串 - 即您不能将日期连接到查询中 (... ='+CONVERT(date, @currentDate)+' ...
)。
您还应该尽可能地尝试参数化动态查询,因为这将减少 Sql 注入面攻击区域。例如,在更新查询中,除了动态列名 (@period
) 之外的所有内容都可以参数化。使用sp_executesql
传递参数,跨动态查询对应类型:
DECLARE @updateQuery as NVARCHAR(max);
SELECT @updateQuery=
N'update tbl_DailyAttend set ' + @period + N'=''true''
where DeptId=@DeptId and SemId=@SemId and SecId=@SecId
and attDate = @currentDate and StuId=@stnId';
sp_executesql @updateQuery,
N'@DeptId int,
@SemId int,
@SecId int,
@DayId int,
@currentDate date,
@stnId as int',
@DeptId = @DeptId,
@SemId = @SemId,
@SecId = @SecId,
@DayId = @DayId,
@currentDate = @currentDate,
@stnId = @stnId';
为了减少对动态列名的注入攻击,您还可以在执行查询之前检查该列是否存在于 table 中(例如来自 sys.columns
)
ALTER proc [dbo].[sp_dosomethingwithStudentAttn] @AttnList as dbo.StudentAttendanceList readonly,@DeptId int,@SemId int,@SecId int,@DayId int,@currentDate date,@period nvarchar(5)
as
declare @IfStudentDayWiseAttnExists as bit,
@updateQuery as varchar(max),
@insertQuery as varchar(max)
begin
set nocount on
declare
@stnId as int,
@stnAttnStatus as nvarchar
declare cur_UpdateInsertStnAttnData cursor forward_only static for
select StudentId,AttdnStatus from @AttnList
open cur_UpdateInsertStnAttnData
if @@CURSOR_ROWS>0
begin
fetch next from cur_UpdateInsertStnAttnData into @stnId,@stnAttnStatus
while @@FETCH_STATUS=0
begin
set @IfStudentDayWiseAttnExists=(select case when exists
(
select * from tbl_DailyAttend
where DeptId=@DeptId and
SemId=@SemId and
SecId=@SecId and
attDate=@currentDate and
StuId=@stnId
)
then CAST(1 AS bit)
else CAST(0 as bit)
end
)
if @IfStudentDayWiseAttnExists='true'
begin
if @stnAttnStatus='true'
begin
select @updateQuery='update tbl_DailyAttend set '+@period+'=''true'' where DeptId='+@DeptId+' and SemId='+@SemId+' and SecId='+@SecId+' and attDate='+CONVERT(date, @currentDate)+' and StuId='+@stnId+''
EXEC (@updateQuery)
end
else
begin
select @updateQuery='update tbl_DailyAttend set '+@period+'=''false'' where DeptId='+@DeptId+' and SemId='+@SemId+' and SecId='+@SecId+' and attDate='+CONVERT(date, @currentDate)+' and StuId='+@stnId+''
EXEC (@updateQuery)
end
end
else
begin
set @insertQuery='insert into tbl_DailyAttend (DeptId,SemId,SecId,DayId,attDate,'+@period+') values ('+@DeptId+','+@SemId+','+@SecId+','+@DayId+','+@currentDate+','+@stnAttnStatus+')'
end
fetch next from cur_UpdateInsertStnAttnData into @stnId,@stnAttnStatus
end
end
end
由于您正在构建动态 Sql,因此您需要将语句构建为字符串 - 即您不能将日期连接到查询中 (... ='+CONVERT(date, @currentDate)+' ...
)。
您还应该尽可能地尝试参数化动态查询,因为这将减少 Sql 注入面攻击区域。例如,在更新查询中,除了动态列名 (@period
) 之外的所有内容都可以参数化。使用sp_executesql
传递参数,跨动态查询对应类型:
DECLARE @updateQuery as NVARCHAR(max);
SELECT @updateQuery=
N'update tbl_DailyAttend set ' + @period + N'=''true''
where DeptId=@DeptId and SemId=@SemId and SecId=@SecId
and attDate = @currentDate and StuId=@stnId';
sp_executesql @updateQuery,
N'@DeptId int,
@SemId int,
@SecId int,
@DayId int,
@currentDate date,
@stnId as int',
@DeptId = @DeptId,
@SemId = @SemId,
@SecId = @SecId,
@DayId = @DayId,
@currentDate = @currentDate,
@stnId = @stnId';
为了减少对动态列名的注入攻击,您还可以在执行查询之前检查该列是否存在于 table 中(例如来自 sys.columns
)