>Да, кто-нибудь вообще подумал о том что делать с этой транзакцией если в ней только 1 ошибка. Отменять все или исключать одну ...
Тут ответ достаточно очевиден: отменять все. Ибо таблица движение, в которую при попытке добавить данные могут молча добавиться НЕ ВСЕ данные, которые туда клали - кошмар для того, кто ее использует. Отдельно не указано, что стоит возвращать набор "плохих" строк - значит тупо блочим все.
4) курсоры и циклы зло, когда цикл выполняется много раз - это дико не оптимально. Можете попробовать в одну таблицу вставить 100000 строк за раз одним запросом и в цикле, и сравнить время. Практически всегда те задачи, где хочется цикл, можно решить через join. Если же алгоритм, которым надо обработать данные, явно итеративный, то можно воспользоваться рекурсивным запросом: https://msdn.microsoft.com/en-us/library/ms186243(... и снова избежать цикла. Как хорошее упражнение, чтобы понять рекурсивные запросы, можете попробовать одним запросом без циклов создать таблицу, которая будет содержать все даты с 1 января 2010 года по текущую.
______________________________________
Также еще немного подумал (внимательно читать задание важно!): нигде не сказано что в "размещении" никто, кроме ваших триггеров, не может изменять данные. А значит, нужно каждый раз полностью пересчитывать эту таблицу.
Итого верное решение по идее примерно такое: вешаем триггеры на Insert-update-delete следующего вида
begin try
begin tran
truncate размещение
insert into размещение
select
<тут по тому, что окажется в таблице "движение" после выполнения операции (вставка и т.п.) полностью пересчитываем таблицу "размещение" (группировка по складам, суммы, все дела)>
commit tran
end try
begin catch
тут если что пошло не так откатываем транзакцию. исключение (вставка отрицательного значения в размещение) должно проброситься наружу само (специально писать ничего не понадобится скорее всего), и выдаться как результат выполнения операции над "движением"
end catch
все-таки такое использование транзакций не есть хорошо. если между begin tran и commit tran возникнет ошибка (в вашем случае, например, если на таблице "размещение" висит ограничение на положительное количество, а вы пытаетесь вставить отрицательное), то произойдет следующее:
- начнется транзакция
- выполнение процедуры завершится
- транзакция останется висеть открытой.
Тут ответ достаточно очевиден: отменять все. Ибо таблица движение, в которую при попытке добавить данные могут молча добавиться НЕ ВСЕ данные, которые туда клали - кошмар для того, кто ее использует. Отдельно не указано, что стоит возвращать набор "плохих" строк - значит тупо блочим все.
>3) как сделать update на 2-1000 разных строк разом без использования какого-либо цикла?
stackoverflow.com/questions/982919/sql-update-quer... - как-то так.
4) курсоры и циклы зло, когда цикл выполняется много раз - это дико не оптимально. Можете попробовать в одну таблицу вставить 100000 строк за раз одним запросом и в цикле, и сравнить время. Практически всегда те задачи, где хочется цикл, можно решить через join. Если же алгоритм, которым надо обработать данные, явно итеративный, то можно воспользоваться рекурсивным запросом: https://msdn.microsoft.com/en-us/library/ms186243(... и снова избежать цикла. Как хорошее упражнение, чтобы понять рекурсивные запросы, можете попробовать одним запросом без циклов создать таблицу, которая будет содержать все даты с 1 января 2010 года по текущую.
______________________________________
Также еще немного подумал (внимательно читать задание важно!): нигде не сказано что в "размещении" никто, кроме ваших триггеров, не может изменять данные. А значит, нужно каждый раз полностью пересчитывать эту таблицу.
Итого верное решение по идее примерно такое: вешаем триггеры на Insert-update-delete следующего вида
begin try
begin tran
truncate размещение
insert into размещение
select
<тут по тому, что окажется в таблице "движение" после выполнения операции (вставка и т.п.) полностью пересчитываем таблицу "размещение" (группировка по складам, суммы, все дела)>
commit tran
end try
begin catch
тут если что пошло не так откатываем транзакцию. исключение (вставка отрицательного значения в размещение) должно проброситься наружу само (специально писать ничего не понадобится скорее всего), и выдаться как результат выполнения операции над "движением"
end catch