powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как в триггере Update обработать Inserted при обновлении более 1 записи
14 сообщений из 14, страница 1 из 1
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022948
Сергей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как в триггере Update обработать Inserted при обновлении более 1 записи.
Т.е. самый простой случай напимер при обновлении 1 и более записей необходимо поменять 1 поле по некоторому условию. Как быть если записей несколько. У меня MS SQL 7.0
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022953
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А какая разница сколько записей обновляется ? Если имеется первичный ключ, то

UPDATE mytable SET myfield = ... FROM mytable a INNER JOIN inserted b ON b.myid = a.myid
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022957
Сергей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я немного упростил вопрос.
Полей 5 и как они поменяются зависит от их содержимого оно почти всегда различно.
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022959
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В MS SQL Server 2000 нет возможности выполнить некую
сложную операцию по отношению к каждой измененной записи
в триггере (в Oracle, например, есть ключевое слово
FOR EACH ROW для достижения этой функциональности). Потому
необходимо самостоятельно реализовывать пробежку по всем
записям в inserted/deleted, лучше, конечно, без курсора,
где это возможно (тот пример, что привел г-н Glory)...
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022961
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь я вас не понимаю.
Какая разница сколько полей(хоть 100) ?

UPDATE mytable SET myfield1 = ... , myfield2 = ... , myfield3 = ...
FROM mytable a INNER JOIN inserted b ON b.myid = a.myid

"и как они поменяются зависит от их содержимого"


UPDATE mytable
SET myfield1 = CASE WHEN LEFT(a.myfield1, 1) = 'A'
THEN RIGHT(a.myfield1, 1) + SUBSTR(a.myfield1, 2, LEN(a.myfield1)-2)+ LEFT(a.myfield1, 1)
WHEN LEFT(a.myfield1, 1) = 'B'
THEN SUBSTR(a.myfield1, 2, 8000 )+ LEFT(a.myfield1, 1)
ELSE a.myfield1
END,
myfield2 = ... , myfield3 = ...
FROM mytable a INNER JOIN inserted b ON b.myid = a.myid
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022962
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2jimmers
В MS SQL Server 2000 нет возможности выполнить некую сложную операцию по отношению к каждой измененной записи

В MS SQL Server 2000 есть UDF
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022978
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
г-ну Glory:

UDF (User-Defined Functions), к сожалению, не могут решить многие
проблемы из-за большого числа ограничений, связанных с самой природой
UDF (т.н. детерминизм).

Пример: для каждой из обновленных записей необходимо вставить в таблицу-лог некий набор записей, определяемый по некому закону...
Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей...

С уважением
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32022982
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей

Ну так набор записей _передать как параметр_ вообще никуда нельзя.

для каждой из обновленных записей необходимо вставить в таблицу-лог некий набор записей, определяемый по некому закону...
Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей .

Что-то не пойму, если _для каждой записи_, то о какой передачи _набора записей_ мы говорим ? Передаем первичнй ключ записи (или вообще все поля) и функция осуществляет какие-то действия _для каждой записи запроса_ (если проводить аналогии с курсором в MSSQL и FOR EACH ROW в Oracle).


ЗЫ
А вообще IMHO использование курсоров и передача набора записей в качестве параметра куда-то для дальнейшей обработки с большой долей вероятности свидетельствует о неправильно спроектированной базе, т.к. говорит об ориентации на позаписную обработку.
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023017
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
г-ну Glory:


create table my_input (mi_id uniqueidentifier)
create table my_output (mo_id uniqueidentifier)

create function my_fn(x_id uniqueidentifier)
return @t table (t_id uniqueidentifier)
as
begin

if x_id = some_value
begin
insert @t select .. from ... where ...
return
end

if x_id = other_value
begin
insert @t select .. from ... where ...
return
end

...
end

Конкретная задача: _каждой_ записи в таблице my_input необходимо по некоторому правилу,
хранящемуся в UDF my_fn(...) сопоставить набор записей и их поместить в таблицу my_output.
Правила лежат в UDF потому, что из могут менять довольно часто.

Например, если у нас:

my_input
========
1
2
3


А правила в my_fn() таковы, что если x_id = 1, то функция вернет

0
1

а в противном случае, вернет x_id, то в my_output дОлжно быть:

my_outut
========
0
1
2
3


Как сие сделать без процедурного подхода (т.е. без курсоров)? Я про это уже спрашивал, сорри, что повторяюсь...
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023021
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
/*эта таблица со всеми правилами*/
create table #rule(rule_id int identity, rule_name varchar(50), rule_output varchar(50))
insert #rule values('rule1', 'Output1')
insert #rule values('rule2', 'Output2')
insert #rule values('rule3', 'Output3')
insert #rule values('rule4', 'Output4')

/*входная таблица*/
create table #input(input_id int identity, input_name varchar(50))
insert #input values('Nothing')
insert #input values('Maybe rule1')
insert #input values('rule1 AND rule2')
insert #input values('rule1, rule2, rule4')
insert #input values('Nothing again')
insert #input values('Stiil Nothing')
insert #input values('rule2 AND rule3')

/*Например, ищем все вхождения input_name в таблице #rule
кроме того для каждой нечетной записи добавляем rule3*/
select * from #input a
inner join #rule b on (PATINDEX('%'+b.rule_name+'%', a.input_name) <> 0)
OR (b.rule_name = 'rule3' AND (a.input_id%2)=1)
order by input_id

/*конечно при большом количестве проверок условие для INNER JOIN сильно разрастется,
НО ведь имеется UNION
Вопрос производительности в следующем и предыдущем случаях нужно будет решать, исходя из конкретных результатов работы
*/
select * from #input a
inner join #rule b on PATINDEX('%'+b.rule_name+'%', a.input_name) <> 0
UNION
select * from #input a
inner join #rule b on (b.rule_name = 'rule3' AND (a.input_id%2)=1)
order by input_id


drop table #rule
drop table #input


В таблицу #rule можно добавить и другие поля, которые нужны для INNER JOIN-a. Главное, чтобы там содержались все правила. Теоритически может быть и несколько таблиц правил.
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023051
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Благодарю за ответ.

Но в Вашем решении нет того, что требуется в задаче.
А именно, для записи в #input (2, 'Maybe rule1'), например, мы
имеем в итоговой выборке:

2 Maybe rule1 1 rule1 Output1

а необходимо

2 Maybe rule1 1 rule1 OutputValue1
2 Maybe rule1 1 rule1 OutputValue2
2 Maybe rule1 1 rule1 OutputValue3
...


где OutputValue1, OutputValue2, OutputValue3 и т.д. и есть
те самые записи, которые сопоставлены по некоторому правилу.

Ну самый простой пример: если по input_name записи из #input мы можем
сказать, что это "Группа", то в итоговую выборку включаем ID всех "Пользователей" из этой "Группы", если же input_name говорит нам,
что это запись в #input соответствует "Пользователю", то в итоговую выборку включаем ID пользователя (т.е. просто перекидываем ID из #input
в итоговую выборку). Суть в том, что правила, по которым можно найти
"Пользователей" из "Группы" могут быть сложными, меняющимися...
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023061
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ув. jimmers. Мне кажется вы просто еще не можете полностью переключиться на то, чтобы полностью мыслить в категориях наборов записей. У меня самого так было после перехода на SQL с десктопных баз данных вроде Foxpro

Так вот еще раз про ИДЕЮ

Одно правило - это набор каких-то проверок для одной записи. Проверки одного правила выстроены ГОРИЗОНТАЛЬНО, т.е. отображаются в столбцы(сколько и каких столбцов нужно для осуществления проверки - это другой вопрос). Собственно проверка основана на использовании JOIN-а со входной таблицей.
Таблица #rule должна содержать ВСЕ ПРАВИЛА.

То, про что вы пишите, я упомянул. Добавляем еще одно поле(читай - проверку) и получаем для rule1 столько записей, сколько нужно

/*эта таблица со всеми правилами*/
create table #rule(rule_id int identity, rule_name varchar(50), rule_name2 varchar(50), rule_output varchar(50))
insert #rule values('rule1', 'Maybe', 'Output1')
insert #rule values('rule2', 'Maybe', 'Output2')
insert #rule values('rule3', 'Maybe', 'Output3')
insert #rule values('rule4', NULL,'Output4')
insert #rule values('SuperRule', 'rule1','SuperOutput')

/*входная таблица*/
create table #input(input_id int identity, input_name varchar(50))
insert #input values('Nothing')
insert #input values('Maybe rule1')
insert #input values('rule1 AND rule2')
insert #input values('rule1, rule2, rule4')
insert #input values('Nothing again')
insert #input values('Stiil Nothing')
insert #input values('rule2 AND rule3')

/*ищем все вхождения input_name в таблице #rule
кроме того для каждой нечетной записи применяем rule3
*/
select * from #input a inner join #rule b on PATINDEX('%'+b.rule_name+'%', a.input_name) <> 0
OR PATINDEX('%'+b.rule_name2+'%', a.input_name) <> 0 OR (b.rule_name = 'rule3' AND (a.input_id%2)=1)
order by input_id

/*конечно при большом количестве проверок условие для INNER JOIN сильно разрастется,
НО ведь имеется UNION
*/
select * from #input a inner join #rule b on PATINDEX('%'+b.rule_name+'%', a.input_name) <> 0
OR PATINDEX('%'+b.rule_name2+'%', a.input_name) <> 0
UNION
select * from #input a inner join #rule b on (b.rule_name = 'rule3' AND (a.input_id%2)=1)
order by input_id

drop table #rule
drop table #input


Ну самый простой пример: если по input_name записи из #input мы можем сказать, что это "Группа", то в итоговую выборку включаем ID всех "Пользователей" из этой "Группы", если же input_name говорит нам, что это запись в #input соответствует "Пользователю", то в итоговую выборку включаем ID пользователя (т.е. просто перекидываем ID из #input в итоговую выборку).
Если таблица #rule будет содержать все Группы с Пользователями вроде такого

rule_name rule_name2
'Группа1' 'Пользователь11'
'Группа1' 'Пользователь12'
'Группа1' 'Пользователь13'
'Группа2' 'Пользователь21'
'Группа2' 'Пользователь22'
'Группа2' 'Пользователь23'


То cвязывая таблицы по rule_name для Группы и по rule_name2 для Пользователя IMHO, вы получите нужный результат. Кроме того, как я уже говорил прежде, можно рассмотреть вариант нескольких таблиц #rule и использования UNION.


Суть в том, что правила, по которым можно найти "Пользователей" из "Группы" могут быть сложными, меняющимися

Таблицу(ы) #rule можно формировать до основного запроса в специальной процедуре, либо ваша UDF может возвращать тип table, но только опять же, содержащий все правила.
Таким образом вы сохраните двойственный подход, если о вам так мил. С одной стороны правила оформлены в виде процедуры, а применение этих правил основано на запросе.
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023074
Фотография jimmers
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь ясно. Предлагается создавать временную таблицу/переменную типа table, в которую заносить всевозможные
сочетания типа "Parent-Child", а потом по ней выполнять JOIN. То есть, в этой таблице необходимо будет хранить
*все* возможные сочетания типа Groups-Users, SuperGroups-Groups и т.п. И при этом ее еще и формировать при
каждом запросе... У меня одних групп около 500.000! Мне кажется, что здесь избыточность ориентированного на наборы
подхода модет проиграть процедурному. Но я все же попробую Ваш вариант и сравню результаты. Благодарю Вас за терпеливое объяснение.
...
Рейтинг: 0 / 0
Как в триггере Update обработать Inserted при обновлении более 1 записи
    #32023079
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предлагается создавать временную таблицу/переменную типа table, в которую заносить всевозможные сочетания типа "Parent-Child", а потом по ней выполнять JOIN. То есть, в этой таблице необходимо будет хранить *все* возможные сочетания типа Groups-Users, SuperGroups-Groups и т.п. И при этом ее еще и формировать при каждом запросе... У меня одних групп около 500.000!

Если ваши 500.000 групп и пользователи уже имеются в виде таблиц, то построение временной таблицы со всеми сочетаниями можно заменить на несколько JOIN-ов к уже существующим. И еще раз позволю себе обратить ваше внимание на возможность использования UNION с запросами, каждый из которых может основываться на своей таблице #rule. Тогда не будет необходимости объединять разноплановые правила в одну промежуточную таблицу правил, а нужно будет как-бы пошагово применить группы правил и шагом выступит UNION.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как в триггере Update обработать Inserted при обновлении более 1 записи
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]