SQL Server 2008-强制转换到nvarchar不工作
我将以下SQL语句作为触发器的一部分,但该触发器不起作用,无法找出原因:SQL Server 2008-强制转换到nvarchar不工作,sql,sql-server,triggers,Sql,Sql Server,Triggers,我将以下SQL语句作为触发器的一部分,但该触发器不起作用,无法找出原因: DECLARE @Orderid INT DECLARE @CountOfOrderItems INT DECLARE @EmployeeID INT DECLARE @EmployeeName NVARCHAR SELECT @Orderid = DELETED.id SET @CountOfOrderItems = (select count(*) from OrderDetails where OrderID =
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表的列数据类型对于sourceobject和logtype都是nvarchar(255)
,对于message则是nvarchar(max)
问题是,当我包含强制转换(@EmployeeName as nvarchar)
位时,消息列中没有输入任何内容,它显示为null。在其他两列中输入数据。将employeename强制转换为varchar
也不起作用
当我删除上面粗体显示的位并使用下面的代码时,它工作了,countoforderitems的转换也工作了
INSERT INTO applicationlog (Sourceobject,Logtype,Message)
VALUES ('Orders table',
'Order deleted',
'Order with ' + CAST(@CountOfOrderItems as varchar) + ' items deleted')
我不知道为什么,希望能得到一些帮助,因为我需要记录删除记录的用户
谢谢
更新
感谢所有的回应。我将employeename声明为VARCHAR(255),并将insert语句编辑为
INSERT INTO applicationlog (Sourceobject,Logtype,Message)
values ('Orders table','Order deleted','Order with ' + CAST(@CountOfOrderItems as varchar(255)) + ' items deleted by ' + coalesce(@EmployeeName,''))
现在,除了@Employeename之外,所有信息都在那里,我认为它返回的是一个空字符串,即使表中存在雇员。因此,在最后一列中,我现在有“3个项目被”
这比以前的空值要好,但为什么@Employeename为空?看起来您在混合数据类型。如果你想让它成为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为null,则整个字符串也将显示null,要避免此问题,可以在查询顶部使用以下语句:
SET CONCAT_NULL_YIELDS_NULL OFF
您使用的
nvarchar
(或varchar
或nchar
或char
)至少三处没有长度。不要这样做。默认长度因上下文而异。因此:
DECLARE @EmployeeName NVARCHAR
事实上:
DECLARE @EmployeeName NVARCHAR(1)
及
事实上:
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;
我认为一个查询更好地显示了您正在做的事情的意图,您不需要发出一堆查询和分配变量。@EmployeeName在声明中已经是NVARCHAR了,为什么要强制执行它?如果它为null,则整个concat都将为null,如果它为null,则必须进行一些检查并添加空字符串-COALESCE(@EmployeeName,,)。。。同样,正如前面提到的,每次您都应该设置一个长度,当您声明它不带长度时,默认值是1您的触发器似乎已断开-
deleted
是一个可能包含0、1或多行的表。将值从它赋给标量变量,SELECT@Orderid=DELETED.id
是有缺陷的(如果这样做有效的话-我还以为您仍然需要一个from
子句来进行查询)。Damien-我的理解是,当一条记录(即一行)被删除时,触发器会运行吗?如果我错了,请纠正我。是的,SELECT@orderid确实返回了一个值,语法看起来很奇怪,但是这里还有其他触发器使用它并且工作正常。谢谢你的回答。我尝试了您的单一查询解决方案,但出现了一个错误。我在上面编辑了一些表名,但仍然有两个错误,都与firstname和lastname有关-错误是“列'employees.lastname'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。”我从已删除的d加入订单o上编辑了此位。d.id=o.id加入员工e上o.employeeid=e.id左加入订单详细信息od.orderid=o.id
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;