2015-09-11 3 views
2

У меня есть следующий SQL заявление как часть триггера, который не работает и не могу понять, почему:SQL Server 2008 - CAST для NVARCHAR не работает

DECLARE @Orderid INT 
DECLARE @CountOfOrderItems INT 
DECLARE @EmployeeID INT 
DECLARE @EmployeeName NVARCHAR 

SELECT @Orderid = DELETED.id 

SET @CountOfOrderItems = (select count(*) from OrderDetails where OrderID = @Orderid) 

SET @EmployeeName = (SELECT Firstname + ' ' + Lastname from Employees where employees.id = 
         (SELECT employeeid from Orders where Orders.id = @Orderid)) 

     INSERT INTO applicationlog (Sourceobject,Logtype,Message) 
     VALUES ('Orders table', 
       'Order deleted', 
       'Order with ' + CAST(@CountOfOrderItems as varchar) + ' items deleted by '+ CAST(@EmployeeName as nvarchar)) 

Типы данных столбцов для applicationlog таблицы все nvarchar(255) для sourceobject и logtype и nvarchar(max) для сообщения.

Проблема заключается в том, что когда я включаю бит CAST(@EmployeeName as nvarchar), в столбце сообщения ничего не вводится, и он показывает значение null. Данные вводятся в двух других столбцах. Также не работает литье рабочего места varchar.

Когда я удаляю бит, выделенный выше и использующий следующий код, он работает, и выполняется кастинг для countoforderitems.

INSERT INTO applicationlog (Sourceobject,Logtype,Message) 
VALUES ('Orders table', 
     'Order deleted', 
     'Order with ' + CAST(@CountOfOrderItems as varchar) + ' items deleted') 

Я понятия не имею, почему и был бы признателен за помощь, как мне нужно зарегистрировать пользователя, который удаляет запись.

Благодаря

UPDATE

Спасибо всем, что откликнулись. Я объявил employeename как VARCHAR (255) и редактировал оператора вставки в

 INSERT INTO applicationlog (Sourceobject,Logtype,Message) 
    values ('Orders table','Order deleted','Order with ' + CAST(@CountOfOrderItems as varchar(255)) + ' items deleted by ' + coalesce(@EmployeeName,'')) 

и теперь вся информация есть, кроме @Employeename, который я думаю, возвращает пустую строку, даже если работник существует в table.So в последнем столбце i теперь есть «3 элемента, удаленные«

Это лучше, чем null раньше, но почему @Employeename пустое?

+0

@EmployeeName уже объявлен NVARCHAR, почему вы его используете? И если он равен нулю, весь ваш concat будет NULL, вам нужно сделать некоторую проверку и добавить пустую строку, если это NULL - COALESCE (@EmployeeName, '') ... Также, как упоминалось, вы должны устанавливать длину каждый раз, когда вы объявите его без длины, по умолчанию 1 –

+4

Ваш триггер, кажется, сломан - 'deleted' - это таблица, которая может содержать 0, 1 или * несколько строк. Присвоение значений из него скалярной переменной 'SELECT @Orderid = DELETED.id' является ошибочным (если это работает даже, я бы подумал, что для этого запроса вам еще нужно предложение' FROM'). –

+0

Damien - я понимаю, что триггер запускается, когда запись, т.е. одна строка удалена? Пожалуйста, исправьте меня, если я ошибаюсь. и да, SELECT @orderid действительно возвращает значение, и синтаксис выглядел нечетным, но здесь есть другие триггеры, которые используют его и работают fine.cheers – Nick

ответ

0

Похоже, вы смешиваете типы данных здесь. Если вы хотите, чтобы это был nvarchar, все это должно быть Nvarchar. Вы должны также указать длину вы хотите выглядеть примерно так:

VALUES ('Orders table', 
       'Order deleted', 
       N'Order with ' + CAST(@CountOfOrderItems as Nvarchar(10)) + N' items deleted by '+ CAST(@EmployeeName as nvarchar(10))) 

Это все сказанное, я не знаю, почему вы бросаете @EmployeeName как NVARCHAR, когда вы уже объявили его как NVARCHAR, это кажется излишним обработать.

Если @EmployeeName равно нулю она также будет показывать нуль для всей строки, чтобы обойти эту проблему вы можете использовать следующее заявление в верхней части вас запрос:

SET CONCAT_NULL_YIELDS_NULL OFF 
2

Вы используете nvarchar (или varchar или nchar или char) без длины, по крайней мере, в трех местах. Не делайте этого. Длина по умолчанию зависит от контекста.Итак:

DECLARE @EmployeeName NVARCHAR 

Это действительно:

DECLARE @EmployeeName NVARCHAR(1) 

И

CAST(@CountOfOrderItems as varchar) 

действительно:

CAST(@CountOfOrderItems as varchar(30)) 

(Хорошо, это, наверное, нормально).

Итак, будьте откровенны в отношении длин. Вам не нужно выделять @EmployeeName для конкатенации строк. И вам не нужно использовать set, потому что вы можете установить значение переменной в select высказыванием:

DECLARE @Orderid INT; 
DECLARE @CountOfOrderItems INT; 
DECLARE @EmployeeID INT; 
DECLARE @EmployeeName NVARCHAR(255); 

SELECT @Orderid = DELETED.id; -- This looks strange. I think you are missing a `from` clause 

select @CountOfOrderItems = count(*) 
from OrderDetails 
where OrderID = @Orderid); 

SELECT @EmployeeName = Firstname + ' ' + Lastname 
from Employees 
where employees.id = (SELECT employeeid from Orders where Orders.id = @Orderid)); 

INSERT INTO applicationlog (Sourceobject, Logtype, Message) 
    VALUES ('Orders table', 
      'Order deleted', 
      'Order with ' + CAST(@CountOfOrderItems as varchar(8000)) + ' items deleted by '+ @EmployeeName ; 

Или, я бы просто отказаться от всего промежуточного материала и сделать:

INSERT INTO applicationlog (Sourceobject, Logtype, Message) 
    SELECT 'Orders table', 'Order deleted', 
      replace(replace('Order with @n items deleted by @by', 
          '@n', count(od.orderid) 
         ), '@by', e.Firstname + ' ' + e.Lastname 
       ) 
    FROM deleted d JOIN 
     orders o 
     on d.id = o.orderId JOIN 
     employees e 
     on o.employeeid = e.employeeid LEFT JOIN 
     orderdetails od 
     on od.orderid = o.orderid; 

Я думаю, что один запрос лучше показывает намерение того, что вы делаете, и вам не нужно выпускать кучу запросов и назначать переменные.

+0

спасибо за ваш отзыв Gordon. Я опробовал решение для одного запроса, но получил ошибку. Я отредактировал некоторые имена таблиц на нем, но все еще получил две ошибки, связанные как с первым, так и с фамилией. Ошибка - это «Столбец». В имени списка «Недопустимое имя» недопустимо, поскольку оно не содержится ни в агрегатной функции, ни в GROUP BY ". – Nick

+0

я редактировал этот бит ОТ удален d РЕГИСТРИРУЙТЕСЬ заказов уплотнительных на d.id = o.Id РЕГИСТРИРУЙТЕСЬ сотрудников электронной на o.employeeid = e.id LEFT JOIN Детали_Заказов од на od.orderid = o.id – Nick

Смежные вопросы