Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Как в триггере Update обработать Inserted при обновлении более 1 записи. Т.е. самый простой случай напимер при обновлении 1 и более записей необходимо поменять 1 поле по некоторому условию. Как быть если записей несколько. У меня MS SQL 7.0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 07:39 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
А какая разница сколько записей обновляется ? Если имеется первичный ключ, то UPDATE mytable SET myfield = ... FROM mytable a INNER JOIN inserted b ON b.myid = a.myid ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 07:59 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Я немного упростил вопрос. Полей 5 и как они поменяются зависит от их содержимого оно почти всегда различно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 08:06 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
В MS SQL Server 2000 нет возможности выполнить некую сложную операцию по отношению к каждой измененной записи в триггере (в Oracle, например, есть ключевое слово FOR EACH ROW для достижения этой функциональности). Потому необходимо самостоятельно реализовывать пробежку по всем записям в inserted/deleted, лучше, конечно, без курсора, где это возможно (тот пример, что привел г-н Glory)... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 08:14 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Теперь я вас не понимаю. Какая разница сколько полей(хоть 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 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 08:17 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
2jimmers В MS SQL Server 2000 нет возможности выполнить некую сложную операцию по отношению к каждой измененной записи В MS SQL Server 2000 есть UDF ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 08:26 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
г-ну Glory: UDF (User-Defined Functions), к сожалению, не могут решить многие проблемы из-за большого числа ограничений, связанных с самой природой UDF (т.н. детерминизм). Пример: для каждой из обновленных записей необходимо вставить в таблицу-лог некий набор записей, определяемый по некому закону... Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей... С уважением ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 10:23 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей Ну так набор записей _передать как параметр_ вообще никуда нельзя. для каждой из обновленных записей необходимо вставить в таблицу-лог некий набор записей, определяемый по некому закону... Тут UDF не помогут, т.к. им нельзя передать в качестве параметра набор записей . Что-то не пойму, если _для каждой записи_, то о какой передачи _набора записей_ мы говорим ? Передаем первичнй ключ записи (или вообще все поля) и функция осуществляет какие-то действия _для каждой записи запроса_ (если проводить аналогии с курсором в MSSQL и FOR EACH ROW в Oracle). ЗЫ А вообще IMHO использование курсоров и передача набора записей в качестве параметра куда-то для дальнейшей обработки с большой долей вероятности свидетельствует о неправильно спроектированной базе, т.к. говорит об ориентации на позаписную обработку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 10:44 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
г-ну 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 Как сие сделать без процедурного подхода (т.е. без курсоров)? Я про это уже спрашивал, сорри, что повторяюсь... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 15:50 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
/*эта таблица со всеми правилами*/ 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. Главное, чтобы там содержались все правила. Теоритически может быть и несколько таблиц правил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.02.2002, 17:00 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Благодарю за ответ. Но в Вашем решении нет того, что требуется в задаче. А именно, для записи в #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 в итоговую выборку). Суть в том, что правила, по которым можно найти "Пользователей" из "Группы" могут быть сложными, меняющимися... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.02.2002, 06:42 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Ув. 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, но только опять же, содержащий все правила. Таким образом вы сохраните двойственный подход, если о вам так мил. С одной стороны правила оформлены в виде процедуры, а применение этих правил основано на запросе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.02.2002, 07:51 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Теперь ясно. Предлагается создавать временную таблицу/переменную типа table, в которую заносить всевозможные сочетания типа "Parent-Child", а потом по ней выполнять JOIN. То есть, в этой таблице необходимо будет хранить *все* возможные сочетания типа Groups-Users, SuperGroups-Groups и т.п. И при этом ее еще и формировать при каждом запросе... У меня одних групп около 500.000! Мне кажется, что здесь избыточность ориентированного на наборы подхода модет проиграть процедурному. Но я все же попробую Ваш вариант и сравню результаты. Благодарю Вас за терпеливое объяснение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.02.2002, 08:50 |
|
||
|
Как в триггере Update обработать Inserted при обновлении более 1 записи
|
|||
|---|---|---|---|
|
#18+
Предлагается создавать временную таблицу/переменную типа table, в которую заносить всевозможные сочетания типа "Parent-Child", а потом по ней выполнять JOIN. То есть, в этой таблице необходимо будет хранить *все* возможные сочетания типа Groups-Users, SuperGroups-Groups и т.п. И при этом ее еще и формировать при каждом запросе... У меня одних групп около 500.000! Если ваши 500.000 групп и пользователи уже имеются в виде таблиц, то построение временной таблицы со всеми сочетаниями можно заменить на несколько JOIN-ов к уже существующим. И еще раз позволю себе обратить ваше внимание на возможность использования UNION с запросами, каждый из которых может основываться на своей таблице #rule. Тогда не будет необходимости объединять разноплановые правила в одну промежуточную таблицу правил, а нужно будет как-бы пошагово применить группы правил и шагом выступит UNION. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.02.2002, 09:13 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32023051&tid=1823891]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
139ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
43ms |
get tp. blocked users: |
1ms |
| others: | 262ms |
| total: | 488ms |

| 0 / 0 |
