有一種方法做什麼的提問要求:我做了一些
在一個觸發器內部測試一個特定表的所有列是否實際參與了一個inser t到那張桌子。如果他們這樣做了,我後來將它們複製到歷史記錄表中。如果他們沒有,那麼回滾和打印只有完整的行可能會插入到報表中。也許他們能夠適應這個自己的需求:
那就是:
[
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 ['[email protected]_columnname+'] from #temp_for_dynamic_sql where ['[email protected]_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 < @actual_num_of_columns ..........
我這樣做是因爲我有一個sp,每次運行時都會向報表中插入一行完整行。沒關係,但我不想讓其他人誤觸這張桌子。甚至不是我自己。我也想保留歷史。所以我讓這個觸發器保留了歷史記錄,還檢查了是否嘗試了沒有值的報告表中的所有列的插入,並進一步向下檢查代碼是否嘗試更新或刪除並回滾。
我想擴大這個允許更新,但其中所有的列設置。 這可能被完成如下:
如果更新嘗試,
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
@ Beenay25的'inserted'表將具有相同的模式,它出現在'INFORMATION_SCHEMA'如果這是任何使用地址。 – 2010-07-09 14:41:49
嗨米奇, 感謝,但我不知道是運行觸發前的列名會是什麼......這就是爲什麼我試圖讓信息從INFORMATION_SCHEMA 的 我得把觸發六十張桌子。我不想硬編碼每個列的名稱:( 我只是想重複使用相同的代碼(很明顯,不同的表名) – Beenay25 2010-07-09 14:46:26
@ Beenay25:寫一個腳本來生成硬連接名稱的觸發器... – 2010-07-09 16:05:57