- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
ALTER TRIGGER [dbo].[ObjectTrade]
ON [dbo].[packets]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@id_key int,
@id_th int,
@date_end datetime,
@date_beg datetime
SET @id_key = (SELECT id_key FROM inserted)
SET @id_th = (SELECT id_th FROM inserted WHERE id_key = @id_key)
SET @date_end = (SELECT date_end FROM inserted WHERE id_key = @id_key)
SET @date_beg = (SELECT date_beg FROM inserted WHERE id_key = @id_key)
IF @id_th = 183
UPDATE packets
SET packets.date_end = CAST('12-05-2014' AS DATE)
WHERE id_key =@id_key
IF (CAST(@date_end AS DATE) BETWEEN '08-03-2014' and '10-03-2014') SET @date_end = '07-03-2014'
IF (CAST(@date_end AS DATE) BETWEEN '01-05-2014' and '04-05-2014') SET @date_end = '30-04-2014'
IF (CAST(@date_end AS DATE) BETWEEN '09-05-2014' and '11-05-2014') SET @date_end = '08-05-2014'
IF (CAST(@date_end AS DATE) BETWEEN '12-06-2014' and '15-06-2014') SET @date_end = '11-06-2014'
IF (CAST(@date_end AS DATE) BETWEEN '02-11-2014' and '04-11-2014') SET @date_end = '01-11-2014'
IF (CAST(@date_end AS DATE) BETWEEN '01-01-2015' and '08-01-2015') SET @date_end = '31-12-2014'
IF DATEPART(WEEKDAY, @date_end) = 7 SET @date_end = DATEADD(DAY, -1, @date_end)
UPDATE packets SET packets.date_end = @date_end WHERE id_key =@id_key
END
Lokich 07.04.2014 16:51 # 0
DBdev 08.04.2014 12:24 # +2
Как писали выше - свалится при массовом апдейте.
Видел решение от продвинутых гуру SQL: SELECT TOP 1 ... И никогда не свалится. Problemz?
> IF @id_th = 183
Ммм...магические цифры, да.
> CAST('12-05-2014' AS DATE)
Ммм...магические даты, да. Первый рабочий день после отмечания дня победы?
> IF (CAST(@date_end AS DATE) BETWEEN '08-03-2014' and '10-03-2014') SET @date_end = '07-03-2014'
> IF (CAST(@date_end AS DATE) BETWEEN '01-05-2014' and '04-05-2014') SET @date_end = '30-04-2014'
> IF (CAST(@date_end AS DATE) BETWEEN '09-05-2014' and '11-05-2014') SET @date_end = '08-05-2014'
> IF (CAST(@date_end AS DATE) BETWEEN '12-06-2014' and '15-06-2014') SET @date_end = '11-06-2014'
> IF (CAST(@date_end AS DATE) BETWEEN '02-11-2014' and '04-11-2014') SET @date_end = '01-11-2014'
> IF (CAST(@date_end AS DATE) BETWEEN '01-01-2015' and '08-01-2015') SET @date_end = '31-12-2014'
И действительно, зачем глобальный справочник времени?
Вот же, все государственные праздники, в самом труЪ месте для этого - триггере! В следующем году обязательно подправим.
> IF DATEPART(WEEKDAY, @date_end) = 7 SET @date_end = DATEADD(DAY, -1, @date_end)
А если воскресенье? Тогда суббота.
defecate-plusplus 08.04.2014 14:18 # 0
в MS SQL нет чтоли for each row?..
DBdev 08.04.2014 14:42 # +3
Соль в том, что конструкция SET @variable = (SELECT bla bla bla) подразумевает, что SELECT bla bla bla вернёт одно и только одно значение.
bormand 08.04.2014 14:53 # 0
DBdev 08.04.2014 15:37 # 0
Нет такого :) Есть INSTEAD OF.
Там такое же название таблицы будет.
Разница в типах DML.
Тип DML - доступные временные таблицы в памяти: INSERT - inserted, DELETE - deleted, UPDATE - inserted & deleted.
Lokich 08.04.2014 16:39 # 0
в SQL Server есть только 2 операции над данными - INSERT и DELETE.
поэтому старые или удаленные данные всегда в DELETED, а новые, или обновленные в INSERTED.
DBdev 08.04.2014 17:12 # 0
FOR | AFTER
AFTER specifies that the DML trigger is fired only when all operations specified in the triggering SQL statement have executed successfully. All referential cascade actions and constraint checks also must succeed before this trigger fires.
AFTER is the default when FOR is the only keyword specified.
Пишешь FOR - получаешь AFTER.
> в SQL Server есть только 2 операции над данными - INSERT и DELETE.
> поэтому старые или удаленные данные всегда в DELETED, а новые, или обновленные в INSERTED.
Не вижу противоречий. Я в последнем своём предложении это и написал.
Lokich 08.04.2014 21:16 # 0
defecate-plusplus 08.04.2014 16:40 # +1
before insert и instead of insert - как бы разные вещи
DBdev 08.04.2014 17:14 # 0
Норм, всё что надо - есть.
> before insert и instead of insert - как бы разные вещи
before insert НЕ НУЖЕН (c) MS
defecate-plusplus 08.04.2014 17:40 # +1
абстрагируясь от идиотизма подмены дат в триггере, на оракле ОП был бы:
1) триггер before insert, которого нет в MS, потому что это глупо сначала инсертить, а потом то же самое апдейтить
2) for each row, которого нет в MS, чтобы не думать, сколько строк было затронуто
3) select col1, col2, col3 into var1, var2, var3 from foo ...; - этого тоже нет в MS?
Lokich 08.04.2014 21:21 # 0
2. в действительности очень мало ситуаций, когда нельзя что-то выполнить без for earch row или через курсоры. не вижу в этом смысла, базы данных создавались для работы с массивом данных.
3. select @value1 = val1 , @value2 = val2, @value3 = val3 from foo...
DBdev 09.04.2014 10:21 # +1
За бизнес логику в триггере (в любой СУБД) - расстрел на месте. Если тех. лид говорит "а по другому никак" - это первый звоночек, что архитектура, таки, гавно. И дальше будет только боль для мейнтейнеров солюшена.
> 1) триггер before insert, которого нет в MS, потому что это глупо сначала инсертить, а потом то же самое апдейтить
Ну пишите полностью свой INSERT в INSTEAD OF триггере с преферансом и поэтессами. И поддерживайте тогда уже всю вставку строки. Зато лишнего апдейта не будет.
> 2) for each row, которого нет в MS, чтобы не думать, сколько строк было затронуто
Тут у ОП проблема в том, что он ТАК написал код, что он работает с одной строкой только, а не у МС проблемы. Как я уже писал выше - не возбраняется обрабатывать виртуальные таблицы inserted и deleted во все щели, как и обычные статические таблицы.
> 3) select col1, col2, col3 into var1, var2, var3 from foo ...; - этого тоже нет в MS?
Как выше писали: select @var1 = col1 , @var2 = col2, @var3 = col3 from foo...
MS не виноват, что некоторым не дано (это возвращаюсь к ОПу) в T-SQL и реляционную модель.
Автор бы написал похожее говнецо и на PL/SQL и ему бы не помогли before insert триггер, for each row и другое написание массового присвоения.
Lokich 09.04.2014 12:27 # +1
с каких это пор?
таблицы read only.
DBdev 11.04.2014 12:19 # +1
И находим:
"Ну, inserted - можно сказать "виртуальная" таблица. Можно и курсор на ней станцевать и любые другие непристойности с SELECT'ом вытворять."
Тут ни слова про модификацию данных в этих таблицах.
Не вижу противоречий.
Lokich 11.04.2014 18:27 # 0
а это тогда как понимать?
DBdev 09.04.2014 10:31 # +2
http://msdn.microsoft.com/en-us/library/ms190752(v=sql.105).aspx
bormand 09.04.2014 10:37 # 0
after update update
after update update
after update update
...
DBdev 08.04.2014 14:43 # 0