有一种方法可以满足提问者的要求:
我在触发器中做了一些事情,测试特定表的所有列是否实际参与了对该表的插入。如果他们这样做了,我后来将它们复制到历史表中。如果没有,则回滚并仅打印完整的行可能会插入到报告表中。也许他们可以根据自己的需要进行调整:
这里是:
[
if exists (select 1 from inserted) and not exists (select 1 from deleted) -- if an insert has been performed
begin -- and we want to test whether all the columns in the report table were included in the insert
declare @inserted_columncount int, @actual_num_of_columns int, @loop_columns int, @current_columnname nvarchar(300),
@sql_test nvarchar(max), @params nvarchar(max), @is_there bit
set @actual_num_of_columns = (
select count(*) from (
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'renameFilesFromTable_report') as z)
set @inserted_columncount = 0
set @loop_columns = 1
declare inserted_columnnames cursor scroll for -- these are not really the inserted ones, but we are going to test them 1 by 1
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'renameFilesFromTable_report'
set @params = '@is_there_in bit output'
open inserted_columnnames
fetch next from inserted_columnnames into @current_columnname
select * into #temp_for_dynamic_sql from inserted -- this is necessary because the scope of sp_executesql does not include inserted pseudo table
while (@loop_columns <= @actual_num_of_columns) -- looping with independent integer arithmetic
begin
set @sql_test = '
set @is_there_in = 0
if exists (select ['+@current_columnname+'] from #temp_for_dynamic_sql where ['+@current_columnname+'] is not null)
set @is_there_in = 1'
exec sp_executesql @sql_test, @params, @is_there output
if @is_there = 1
begin
fetch next from inserted_columnnames into @current_columnname
set @inserted_columncount = @inserted_columncount + 1
set @loop_columns = @loop_columns + 1
end
else if @is_there <> 1
begin
fetch next from inserted_columnnames into @current_columnname
set @loop_columns = @loop_columns + 1
end
end
close inserted_columnnames
deallocate inserted_columnnames
-- at this point we hold in two int variables the number of columns participating in the insert and the total number of columns
]
如果@inserted_columncount
我这样做是因为我有一个 sp 每次运行时都会在报表表中插入 1 个完整的行。没关系,但我不希望其他人误触那张桌子。连我自己都没有。我也想保留历史。所以我做了这个触发器来保留历史记录,但也检查是否尝试插入而没有报告表中所有列的值,并进一步检查代码是否尝试更新或删除并回滚。
我正在考虑扩展它以允许更新,但其中所有列都已设置。
这可以按如下方式完成:
如果尝试更新,
and exists (
select possibly_excluded.COLUMN_NAME from (
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'renameFilesFromTable_report') as possibly_excluded
group by possibly_excluded.COLUMN_NAME
having COLUMN_NAME not in (
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'renameFilesFromTable_report' and
sys.fn_IsBitSetInBitmask(@ColumnsUpdated, COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'ColumnID')) <> 0)
)
begin
rollback transaction
print 'Only updates that set the values for a complete row are allowed on the report table..'
end