Если в соединении выполняется операция update, то можно написать триггер, в теле которого можно воспользоваться функциями update или columns_updated для проверки того какие конкретно столбцы были обновлены. Наиболее удобной функций является columns_updated, так как она возвращает битовую маску, где каждый бит соответствует номеру обновленного столбца.
Что бы правильно пользоваться этой функцией, нужно знать два факта.
Во-первых, байты, образующие биты, идут справа налево. Во-вторых, функция возвращает строку varbinary. И в ней первый справа байт описывает биты для первых восьми столбцов, второй правый байт показывает биты для столбцов с 9-ого по 16-ый и так далее.
Число байт, которое вернет columns_updated, равно отношению числа столбцов к 8 (плюс 1, если число столбцов не кратно 8). Для определения списка номеров столбцов в самом общем случае, независимо от числа столбцов, можно использовать такой запрос:
Для удобства можно добавить соединение на sys.columns чтобы сразу определить имена обновленных столбцов. Также инкапсулируем все в табличную функцию:
В последнем подзапросе используется row_number для получения номеров столбцов. Это важно, так как column_id могут не идти последовательно (например, если ранее был создан столбец, затем удален, а затем появились еще новые столбцы). При использовании данной функции следует лишь удостовериться что пользователь, выполняющий update, сможет получить доступ к sys.columns. Если такого доступа нет, то можно создавать функцию с опцией exec as, чтобы она выполнялась от имени пользователя, имеющего соответствующие права на просмотр метаданных.
Что бы правильно пользоваться этой функцией, нужно знать два факта.
Во-первых, байты, образующие биты, идут справа налево. Во-вторых, функция возвращает строку varbinary. И в ней первый справа байт описывает биты для первых восьми столбцов, второй правый байт показывает биты для столбцов с 9-ого по 16-ый и так далее.
Число байт, которое вернет columns_updated, равно отношению числа столбцов к 8 (плюс 1, если число столбцов не кратно 8). Для определения списка номеров столбцов в самом общем случае, независимо от числа столбцов, можно использовать такой запрос:
declare
@varByteCols varbinary
( max
) = columns_updated ()
;
with
Cols
as
(
select iCol
from
(
select
1 as iCol
union
all
select
2
union
all
select
4
union
all
select
8
union all
select 16
union all
select
32
union
all
select
64
union
all
select
128
) Cols
),
Bytes
as
(
select 1 as iByteNum
union
all
select iByteNum + 1
from Bytes
where iByteNum + 1 <= len ( @varByteCols )
)
select
iColNum = ( Bytes.iByteNum - 1 ) * 8 + log ( Cols.iCol, 2 ) + 1
from
Bytes
inner
join
Cols on substring ( @varByteCols, Bytes.iByteNum, 1 ) & Cols.iCol <> 0Для удобства можно добавить соединение на sys.columns чтобы сразу определить имена обновленных столбцов. Также инкапсулируем все в табличную функцию:
if
object_id ( N'dbo.GetUpdCols', N'IF' ) is null
exec ( N'create function
dbo.GetUpdCols ( @i int ) returns table as return ( select 1 as i )' )
go
alter
function dbo.GetUpdCols ( @varByteCols varbinary ( max ), @vcTabName varchar ( 400 ) )
returns table
as
return
(
with Cols
as
(
select
iCol
from
(
select
1 as iCol
union all
select
2
union all
select
4
union all
select
8
union all
select
16
union all
select
32
union all
select
64
union all
select 128
) Cols
), Bytes
as
(
select
1 as iByteNum
union
all
select
iByteNum + 1
from
Bytes
where
iByteNum + 1 <= len ( @varByteCols )
)
select ColNums.name
from
Bytes
inner
join
Cols
on substring ( @varByteCols, Bytes.iByteNum, 1 ) & Cols.iCol <> 0
inner
join
(
select
name, iColNum = row_number () over ( order by column_id asc )
from
sys.columns
where
object_id = object_id ( @vcTabName, N'U' )
) ColNums on ColNums.iColNum = ( Bytes.iByteNum - 1 ) * 8 + log ( Cols.iCol, 2 ) + 1
)
goВ последнем подзапросе используется row_number для получения номеров столбцов. Это важно, так как column_id могут не идти последовательно (например, если ранее был создан столбец, затем удален, а затем появились еще новые столбцы). При использовании данной функции следует лишь удостовериться что пользователь, выполняющий update, сможет получить доступ к sys.columns. Если такого доступа нет, то можно создавать функцию с опцией exec as, чтобы она выполнялась от имени пользователя, имеющего соответствующие права на просмотр метаданных.
Комментариев нет:
Отправить комментарий