Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
Прошу помощи Господа!
Есть триггрер
ALTER TRIGGER [dbo].[i_mr] ON [dbo].[monitoring_report]
AFTER INSERT
AS 
BEGIN
 DECLARE @Rep varchar(255)
 SELECT @Rep = status
 FROM inserted
 SELECT REPLACE(@Rep,'критическая ошибка.','заменено')
 SELECT status = @Rep
 FROM inserted
END

Цель триггера заменить значение поля status добавляемой строки на измененное.
Не совсем разбираюсь в Trasact-SQL поэтому подскажите что не правильно.
9 дек 11, 12:42    [11735751]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
tpg
Member

Откуда: Novosibirsk
Сообщений: 23902
Да всё неправильно...
Во-первых, он написан из предположения, что в виртуальной таблице inserted содержится только одна строка, тогда как, в ней столько строк, сколько затронула вызвавшая триггер операция.
Во-вторых, в триггере не заменяются никакие значения ни в одной таблице, а просто меняется значение переменной и потом выводится "в воздух".
В-третьих, вы не сказали название столбца/цов первичного ключа исходной таблицы, чтобы строки виртуальной таблицы можно было "привязать" к строкам исходной.
9 дек 11, 12:49    [11735795]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Glory
Member

Откуда:
Сообщений: 104751
Значение в таблице меняется командой UPDATE
А SELECT REPLACE(@Rep,'критическая ошибка.','заменено') меняет только вашу локальную переменную @Rep
9 дек 11, 12:50    [11735801]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
tpg
Да всё неправильно...
Во-первых, он написан из предположения, что в виртуальной таблице inserted содержится только одна строка, тогда как, в ней столько строк, сколько затронула вызвавшая триггер операция.
Во-вторых, в триггере не заменяются никакие значения ни в одной таблице, а просто меняется значение переменной и потом выводится "в воздух".
В-третьих, вы не сказали название столбца/цов первичного ключа исходной таблицы, чтобы строки виртуальной таблицы можно было "привязать" к строкам исходной.


вот с "Во-вторых" у меня и загвоздка
"В-третьих" Исходная таблица monitorring_report в которую добавляются данные не имеет первичного ключа

Я исходил из следующего алгоритма когда пытался создать этот триггер:
1. присваиваем переменной @Rep значение столбца которое нужно изменить
2. Изменяем переменную как нужно
3. Присваиваем столбцу новое значение из переменной

или есть возможность сделать это проще?
9 дек 11, 13:35    [11736285]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Reality_Gluk, при отутствии PK или AK и нежелании их заводить, вам остается смотреть в сторону триггера instead of insert. И забудте про переменные -- все делается единственной инструкцией insert.
9 дек 11, 14:09    [11736683]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
tpg
Member

Откуда: Novosibirsk
Сообщений: 23902
Reality_Gluk
"В-третьих" Исходная таблица monitorring_report в которую добавляются данные не имеет первичного ключа...
О! хоспади!... До коле?!
Ну а хоть какой-нить уникальный столбец или сочетание столбцов есть?

Если без ПК или уникального констрента, то, наверное только INSTEAD OF INSERT-триггер прокатит.
9 дек 11, 14:13    [11736731]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
invm
И забудте про переменные -- все делается единственной инструкцией insert.

как? не пойму. может объяснишь популярнее, пожалуйста?
9 дек 11, 14:47    [11737091]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Reality_Gluk
invm
И забудте про переменные -- все делается единственной инструкцией insert.

как? не пойму. может объяснишь популярнее, пожалуйста?
create trigger [dbo].[i_mr] on [dbo].[monitoring_report]
instead of insert
as 
begin
 if @@rowcount = 0
  return;
 
 set nocount on;
 
 insert into [dbo].[monitoring_report]
  (field1, field2, ..., fieldN, status)
  select
   field1, field2, ..., fieldN, replace(status, 'критическая ошибка.', 'заменено')
  from
   inserted;
end;
9 дек 11, 16:01    [11737853]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
invm
Reality_Gluk
пропущено...

как? не пойму. может объяснишь популярнее, пожалуйста?
create trigger [dbo].[i_mr] on [dbo].[monitoring_report]
instead of insert
as 
begin
 if @@rowcount = 0
  return;
 
 set nocount on;
 
 insert into [dbo].[monitoring_report]
  (field1, field2, ..., fieldN, status)
  select
   field1, field2, ..., fieldN, replace(status, 'критическая ошибка.', 'заменено')
  from
   inserted;
end;
Лучше так:
create trigger [dbo].[i_mr] on [dbo].[monitoring_report]
instead of insert
as 
 if exists(select * FROM inserted)
 begin
 
  set nocount on;
 
  insert [dbo].[monitoring_report](field1, field2, ..., fieldN, status)
  select field1, field2, ..., fieldN, replace(status, 'критическая ошибка.', 'заменено')
  from inserted;
 end;
9 дек 11, 16:16    [11738029]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
iap, ага, лучше.
Все никак к возможности мержа не привыкну...
9 дек 11, 16:37    [11738252]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
Спасибо Господа огромное:)
10 дек 11, 07:39    [11740906]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
А еще вот такой вопрос. Допустим у меня в поле status надо искать и заменять несколько разных значений, как сделать чтобы триггер отслеживал и менял их автоматически?
Например replace(status, 'критическая ошибка.', 'заменено')
replace(status, 'Внимание.', '!')
и так далее
Не создавать же десять триггеров с разными значениями функции REPLACE
10 дек 11, 07:50    [11740908]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
aleks2
Guest
Reality_Gluk
А еще вот такой вопрос. Допустим у меня в поле status надо искать и заменять несколько разных значений, как сделать чтобы триггер отслеживал и менял их автоматически?
Например replace(status, 'критическая ошибка.', 'заменено')
replace(status, 'Внимание.', '!')
и так далее
Не создавать же десять триггеров с разными значениями функции REPLACE


Конечно нет. Создают ОДНУ таблицу с парами замен


CREATE TABLE [dbo].[ReplacePairs](
[SearchStr] [nvarchar](256) NOT NULL,
[ReplaceStr] [nvarchar](256) NOT NULL,
[OrdNum] [int] NOT NULL,
CONSTRAINT [PK_ReplacePairs] PRIMARY KEY CLUSTERED
(
[OrdNum] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
go

CREATE FUNCTION [dbo].[ReplaceByTable]
(
@Str nvarchar(4000)
)
RETURNS nvarchar(4000)
AS
BEGIN
SELECT @Str=REPLACE(@Str, SearchStr, ReplaceStr) FROM dbo.ReplacePairs order by OrdNum
RETURN @Str
END
go
select dbo.ReplaceByTable('критическая ошибка.jfkdsf Внимание.')
10 дек 11, 09:37    [11740950]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 659
Reality_Gluk,
Можно, конечно, как aleks2 пердлагет. А можно и попроще...
replace(replace(status, 'Внимание.', '!'), 'критическая ошибка.', 'заменено')

Только нужно помнить, что replace заменяет все вхождения, и зависит от разных настроек (COLLATE)
DECLARE @t TABLE ( s1 NVARCHAR(100) COLLATE Cyrillic_General_CI_AI
                  ,s2 NVARCHAR(100) COLLATE Cyrillic_General_BIN
                 )

INSERT INTO @t(s1, s2)
SELECT  'Совсем не Критическая ошибка, так, обратите внимание...'
      , 'Совсем не Критическая ошибка, так, обратите внимание...'

SELECT  REPLACE(REPLACE(s1, 'критическая ошибка', 'заменено'), 'Внимание.', '!')
      , REPLACE(REPLACE(s2, 'критическая ошибка', 'заменено'), 'Внимание.', '!')
    FROM @t


-------------------------------------- -----------------------------------------------------------
Совсем не заменено, так, обратите !..  Совсем не Критическая ошибка, так, обратите внимание...
10 дек 11, 09:47    [11740956]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
aleks2
Guest
Guf
А можно и попроще...
replace(replace(status, 'Внимание.', '!'), 'критическая ошибка.', 'заменено')


Не утомитесь replace-ы ваять?

Более быстрый, более документированный вариант, но с ограничением <=100 пар замен

CREATE FUNCTION [dbo].[ReplaceByTableEx] 
(@str nvarchar(4000))
RETURNS TABLE 
AS
RETURN 
( with strs as (
     select @str as string, 1 as n
     UNION ALL
     select REPLACE(S.string, R.SearchStr, R.ReplaceStr) as string, S.n+1 as n
     from  strs S INNER JOIN dbo.ReplacePairs R on S.n=R.OrdNum
  )
  SELECT TOP 1 string, n FROM strs ORDER BY n DESC
)
go
declare @t table(s nvarchar(100))

insert @t
VALUES('критическая ошибка. jfkdsf Внимание.')
insert @t
VALUES('критическая ошибка. j 73848fkdsf Внимание.')

select T.*, X.string
FROM @t T CROSS APPLY (select * FROM dbo.ReplaceByTableEx(T.s) Z) X
10 дек 11, 10:04    [11740966]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 659
aleks2
Не утомитесь replace-ы ваять?

2 - нет
22 - наверное, да
Потому и написал, можно и так и сяк...

"более документированный вариант" - можно ссылку?
10 дек 11, 10:12    [11740972]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
aleks2
Guest
Guf
"более документированный вариант" - можно ссылку?

Вам ссылку на документацию по CTE?
10 дек 11, 10:56    [11740990]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 659
aleks2,

Не, на СТЕ не надо, спасибо. Я думал, есть "Более быстрый, более документированный вариант" как сделать реплейс до ста раз
10 дек 11, 11:27    [11741039]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
Reality_Gluk
Member

Откуда:
Сообщений: 6
Видимо Я задачу которая меня интересует не правильно изложил. Опишу задачу конкретнее.
Есть таблица monitoring_report в которой есть поле status. В это поле копируется из внешних источников информация следующего вида:
1 запись: критическая ошибка. (нет сигнала от автомата)
2 запись: критическая ошибка. (Кончилась бумага)
3 запись: критическая ошибка. (нет сигнала от автомата)
4 запись: критическая ошибка. (Принтер не исправен или зажевана бумага)
5 запись: критическая ошибка. (Автообновление: ошибка связи по сети интернет)
6 запись: Внимание. (Принтер не исправен или зажевана бумага)
7 запись: Внимание. (Принтер не исправен или зажевана бумага)
8 запись: Внимание. (Принтер не исправен или зажевана бумага)

Мне нужно чтобы перед добавлением в базу данных эти строки автоматически приводились к виду:
1 запись: (нет сигнала от автомата)
2 запись: (Кончилась бумага)
3 запись: (нет сигнала от автомата)
4 запись: (Принтер не исправен или зажевана бумага)
5 запись: (Автообновление: ошибка связи по сети интернет)
6 запись: (Принтер не исправен или зажевана бумага)
7 запись: (Принтер не исправен или зажевана бумага)
8 запись: (Принтер не исправен или зажевана бумага)

к примеру вот так

Триггеры которые написали invm и iap решают проблему с заменой в строке, но строки бывают разные.
Я решил эту проблему на стороне приложения которое заливает данные в таблицу, но это не целесообразно когда можно передать эту функцию серверу.
10 дек 11, 12:00    [11741093]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
запись: Внимание
Guest
Reality_Gluk
Видимо Я задачу которая меня интересует не правильно изложил. Опишу задачу конкретнее.
Есть таблица monitoring_report в которой есть поле status. В это поле копируется из внешних источников информация следующего вида:
1 запись: критическая ошибка. (нет сигнала от автомата)
6 запись: Внимание. (Принтер не исправен или зажевана бумага)

Мне нужно чтобы перед добавлением в базу данных эти строки автоматически приводились к виду:
1 запись: (нет сигнала от автомата)
8 запись: (Принтер не исправен или зажевана бумага)

к примеру вот так

Триггеры которые написали invm и iap решают проблему с заменой в строке, но строки бывают разные.
Я решил эту проблему на стороне приложения которое заливает данные в таблицу, но это не целесообразно когда можно передать эту функцию серверу.

вот в таких ситуациях сначала проблему надо описывать, а не спрашивать почему триггер не срабатывает.
есть мнение что вы решаете задачу не на той стороне.
наиболее разумным решением есть некий посредник, который будет приводить все сообщения от "внешних источников" к установленному виду. и это не триггер. есть такое мнение.
это DTS, сервис, некий клиент, на крайняк проца. форматирование сообщений - это не задача таблицы или ее триггера.
это не правило, не ограничение, мнение таблицы не спрашивали - что складываем, то и хранится. пусть в своем формате, пусть раскладывает по разным столбцам, но не режет половину вставляемого текста.
не нужен какой-то текст - не вставляйте.
10 дек 11, 13:53    [11741381]     Ответить | Цитировать Сообщить модератору
 Re: Триггер не срабатывает. Помогите  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Reality_Gluk, вот вам пример:
declare @s varchar(100) = 'критическая ошибка. (Автообновление: ошибка связи по сети интернет)';

select
 substring(@s, charindex('(', @s), len(@s) - charindex('(', @s) + 1);
10 дек 11, 13:54    [11741383]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить