SQL Server 2008 - CAST 到 nvarchar 不起作用
Posted
技术标签:
【中文标题】SQL Server 2008 - CAST 到 nvarchar 不起作用【英文标题】:SQL Server 2008 - CAST to nvarchar not working 【发布时间】:2015-09-11 10:36:57 【问题描述】:我有以下 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 = @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)
位时,消息列中没有输入任何内容,并且显示为空。在其他两列中输入数据。将员工名称转换为 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 INTO applicationlog (Sourceobject,Logtype,Message)
values ('Orders table','Order deleted','Order with ' + CAST(@CountOfOrderItems as varchar(255)) + ' items deleted by ' + coalesce(@EmployeeName,''))
现在所有信息都在那里,除了我认为返回空字符串的@Employeename,即使员工存在于表中。所以在最后一列中,我现在有 “3 个项目被“删除”强>
哪个比之前的null好,但是为什么@Employeename是空白的呢?
【问题讨论】:
@EmployeeName 在声明中已经是 NVARCHAR,你为什么要转换它?如果它是空的,你的整个连接将是空的,你必须做一些检查并添加空字符串,如果它是空的 - COALESCE(@EmployeeName,'')......同样就像提到你应该每次设置一个长度,当你声明它没有长度,默认为 1 您的触发器似乎已损坏 -deleted
是一个可能包含 0、1 或 多个 行的表。将值从它分配给一个标量变量,SELECT @Orderid = DELETED.id
是有缺陷的(如果这甚至有效 - 我原以为您仍然需要该查询的 FROM
子句)。
Damien - 我的理解是触发器在一条记录(即一行被删除)时运行?如果我错了,请纠正我。是的,SELECT @orderid 确实返回了一个值,并且语法看起来确实很奇怪,但是这里还有其他触发器可以使用它并且工作正常。干杯
【参考方案1】:
您至少在三个地方使用了没有长度的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;
我认为单个查询可以更好地显示您正在做的事情的意图,并且您不需要发出一堆查询并分配变量。
【讨论】:
感谢您的回复戈登。我尝试了您的单一查询解决方案,但出现错误。我在上面编辑了一些表名,但仍然出现 2 个错误,都与名字和姓氏有关 - 错误是“列 'employees.Lastname' 在选择列表中无效,因为它不包含在聚合函数或 GROUP 中BY 子句。” 我编辑了这个位 FROM deleted d JOIN orders o on d.id = o.Id JOIN employees e on o.employeeid = e.id LEFT JOIN orderdetails od on od.orderid = o.id 【参考方案2】:看起来您在这里混合了数据类型。如果您希望它是 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
【讨论】:
以上是关于SQL Server 2008 - CAST 到 nvarchar 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Server 2000/2005/2008 中使用 FLOAT 转换小数位数
将 Nvarchar 转换为 Int 失败的 SQL Server 2008