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

Откуда:
Сообщений: 21
Доброго времени суток всем!
К сожалению мне плоховато дается SQL. В общем то проблема следующая. Есть у меня небольшая табличка. Есть там столбцы "Дата" и "Смена". Дата пишется со временем, дата особого значения не имеет, а вот время да. Есть 3 варианта: XXXX-XX-XX 00:00:00.000, XXXX-XX-XX 08:00:00.000 и XXXX-XX-XX 16:00:00.000. В зависимости от того какое из этих времен стоит должно быть значение 1,2 или 3 в столбике "Смена". Написал я следующий код:

USE [DBCurs]
GO
/****** Object:  Trigger [dbo].[Number_Smena]    Script Date: 08.03.2017 15:58:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--====================================
--  Create database trigger template 
--====================================
ALTER TRIGGER [dbo].[Number_Smena] 
ON [dbo].[РабочийПроцесс] 
AFTER INSERT, UPDATE
AS 
BEGIN 
IF (select cast(dbo.РабочийПроцесс.Дата as time) [time] FROM dbo.РабочийПроцесс )=convert(time,'00:00',101)
      UPDATE dbo.РабочийПроцесс SET Смена = 1  WHERE Смена IN(SELECT Смена)
ELSE IF (select cast(dbo.РабочийПроцесс.Дата as time) [time] FROM dbo.РабочийПроцесс)=convert(time,'08:00',101)
       UPDATE dbo.РабочийПроцесс SET Смена = 2
ELSE
       UPDATE dbo.РабочийПроцесс SET Смена = 3
 END

Вытаскиваю тут время из datetime, проверяю его и соответственно присваиваю значение. Если запускать этот код просто как запрос, то значения меняются. А вот если запускать его триггером, то вылезает ошибка:

Строки не были обновлены.

Данные в строке 3 не были зафиксированы.
Источник ошибки: .Net SqlClient Data Provider.
Сообщение об ошибке: Вложенный запрос вернул больше одного значения. Это запрещено, когда вложенный запрос следует после =, !=, <, <=, >, >= или используется в качестве выражения.

Выполнение данной инструкции было прервано.

Насколько я понял по гуглу, проблема моя в том, что этот триггер будет работать только если в таблице есть одна строка, а если их несколько то запрос возвращает несколько значений и соответственно падает. Далее насколько я понял, проблема решается с помощью команд IN, JOIN или EXISTS, но вот как их применить кокнретно к своему случая я вообще не понимаю. В интернете есть примеры, но по ним к сожалению не получается.
8 мар 17, 14:06    [20274395]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
player95
Member

Откуда:
Сообщений: 21
player95
WHERE Смена IN(SELECT Смена)

Вот это лишнее в коде, осталось после какой то очередной попытки решить проблему
8 мар 17, 14:10    [20274402]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
aleks2
Guest
player95
IF (select cast(dbo.РабочийПроцесс.Дата as time) [time] FROM dbo.РабочийПроцесс )=convert(time,'00:00',101)


Поведай нам, страдалец, чего ты хотел ЭТИМ сказать?

Или у тя в dbo.РабочийПроцесс ОДНА строка?
8 мар 17, 14:26    [20274443]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
player95
Member

Откуда:
Сообщений: 21
Строк несколько, хотел сравнить время.

Вот так сейчас переделал, вроде работает:

USE [DBCurs]
GO
/****** Object:  Trigger [dbo].[Number_Smena]    Script Date: 08.03.2017 16:28:50 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--====================================
--  Create database trigger template 
--====================================
ALTER TRIGGER [dbo].[Number_Smena] 
ON [dbo].[РабочийПроцесс] 
AFTER INSERT, UPDATE
AS 
BEGIN 
IF (select cast(Дата as time) [time] FROM inserted )=convert(time,'00:00',101)
      UPDATE dbo.РабочийПроцесс SET Смена = 1
ELSE IF (select cast(Дата as time) [time] FROM inserted)=convert(time,'08:00',101)
       UPDATE dbo.РабочийПроцесс SET Смена = 2
ELSE
       UPDATE dbo.РабочийПроцесс SET Смена = 3
 END
8 мар 17, 14:36    [20274467]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
Massa52
Member

Откуда:
Сообщений: 382
player95,
Тут у тебя может вернуться несколько значениий
(select cast(Дата as time) [time] FROM inserted )

И ты эти несколько сравниваешь со скалярным(одним) выражением.
Результат - тяжело представить.
- inserted - это тоже таблица. Там не обязательно одна строка.
8 мар 17, 14:44    [20274490]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
aleks2
Guest
player95
Строк несколько, хотел сравнить время.

Вот так сейчас переделал, вроде работает:



Поверь мне - это иллюзия.

Твой опус не может "работать".
8 мар 17, 15:25    [20274626]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
player95
Member

Откуда:
Сообщений: 21
Да я уже посмотрел, если редактировать или добавлять несколько строк то проблемы.
8 мар 17, 15:28    [20274632]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
aleks2
Guest
ALTER TRIGGER [dbo].[Number_Smena] 
ON [dbo].[РабочийПроцесс] 
AFTER INSERT, UPDATE
AS 
BEGIN 

  with i as ( select * 
                        , сменаX = case cast(Дата as time) 
                                         when convert(time,'00:00',101) then 1
                                         when convert(time,'08:00',101) then 2
                                         else 3
                                      end
                    from inserted 
               )
    update t set Смена = i.сменаX
        from [dbo].[РабочийПроцесс] as t inner join i on i.id = t.id
        where exists( select t.Смена except select i.сменаX )
  ;

 END
8 мар 17, 15:35    [20274657]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
player95
Member

Откуда:
Сообщений: 21
Большое спасибо! А вы можете, кратко пояснить как все это работает?

with i as ( select * 
//with i as не очень понимаю как работает

                     , сменаX = case cast(Дата as time) 
                                         when convert(time,'00:00',101) then 1
                                         when convert(time,'08:00',101) then 2
                                         else 3
                                      end
                    from inserted 
               )

Тут насколько я понимаю создаем переменную, в которой проверяем само условие?

 update t set Смена = i.сменаX
        from [dbo].[РабочийПроцесс] as t inner join i on i.id = t.id
        where exists( select t.Смена except select i.сменаX )
  ;

Первая строка update, обновляем то что получилось после прохождения условия, а вот у 2 последних строк, тоже не очень понимаю механизм работы.
8 мар 17, 15:53    [20274750]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
Шыфл
Member

Откуда: Прага
Сообщений: 776
player95,

with i as ( select * 

                     , сменаX = case cast(Дата as time) 
                                         when convert(time,'00:00',101) then 1
                                         when convert(time,'08:00',101) then 2
                                         else 3
                                      end
                    from inserted 
               )

Это код объявляет таблицу i, в которую помещает * из инсертед + вычисляет сменаХ для каждой записи.

Далее в коде идёт update [dbo].[РабочийПроцесс] as t
 update t set Смена = i.сменаX
 from [dbo].[РабочийПроцесс] as t inner join i on i.id = t.id
        where exists( select t.Смена except select i.сменаX )


Где t соединяется с i через id

А последняя строчка - это выбор того, где Смена ещё не заполнена. Может быть и что-то вроде
where t.Смена is null
8 мар 17, 19:33    [20275275]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с написанием триггера (запрос вернул больше одного значения)  [new]
player95
Member

Откуда:
Сообщений: 21
Спасибо всем отписавшимся!
9 мар 17, 19:05    [20279153]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить