[英]SQL Server--Setting column value during insert using trigger
I have a table with the following columns: 我有一个包含以下列的表:
id, xml, receivedDate, processed, processedDateTime, orderNumber id,xml,receivedDate,processed,processedDateTime,orderNumber
id, receivedDate, and processed all have default values. id,receivedDate和processed都具有默认值。
The XML being stored in the xml column looks like this: 存储在xml列中的XML如下所示:
<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:BusinessUnitId>11</v1:BusinessUnitId>
<v1:OrderNumber>964806604</v1:OrderNumber>
<v1:OrderStatusCode>RDD</v1:OrderStatusCode>
<v1:StatusDateTime>2016-04-12T01:16:28</v1:StatusDateTime>
<v1:RDD_Date>2016-04-19T00:00:00</v1:RDD_Date>
</v1:OrderStatus>
When the XML is inserted to the table, I need to grab the value for OrderNumber and set it in the orderNumber column. 当XML插入到表中时,我需要获取OrderNumber的值并将其设置在orderNumber列中。 I developed a trigger to try to accomplish this, but instead of setting the the value in only the newly inserted row, it sets the value for ALL the rows in the table. 我开发了一个触发器来尝试完成此操作,但它不是仅在新插入的行中设置值,而是设置表中所有行的值。
My trigger looks like: 我的触发器看起来像:
declare @ordernumber varchar(50)
select @ordernumber=(select xml.value('(//*:OrderNumber)[1]', 'varchar(max)') as orderNumber from inserted)
Update [dbo].[dell.des.OCIMessages]
set orderNumber=@ordernumber
END
I have another trigger on a different table which joins on the orderNumber value between these two tables and I use this other trigger after an insert/update to find the row with the matching orderNumber and processed=0 and then set processed=1 and also set the processedDateTime field. 我在另一个表上有另一个触发器,它连接在这两个表之间的orderNumber值,我在插入/更新后使用另一个触发器来查找匹配orderNumber并处理= 0的行,然后设置processed = 1并设置processedDateTime字段。
Unfortunately, since my first trigger is updating all the rows to use the same order number value, my second trigger inadvertently always updates all the rows because the ordernumber values are the same for every row in my table. 不幸的是,由于我的第一个触发器是更新所有行以使用相同的订单号值,我的第二个触发器无意中总是更新所有行,因为我的表中的每一行的ordernumber值都相同。
Can someone please shed some light on what is wrong with my trigger so that it only updates just the inserted row? 有人可以说明我的触发器有什么问题,以便它只更新插入的行吗?
BTW, I'm only ever inserting a single row at a time, so I don't have to worry about my trigger have to deal with multiple records. 顺便说一句,我一次只插入一行,所以我不必担心我的触发器必须处理多个记录。
Thanks! 谢谢!
You could use a where condition on your update: 您可以在更新中使用where条件:
declare @ordernumber varchar(50), @id int
select @ordernumber= xml.value('(//*:OrderNumber)[1]', 'varchar(max)') as orderNumber, @id = id from inserted
Update [dbo].[dell.des.OCIMessages]
set orderNumber=@ordernumber
where id = @id
END
Or you could just use the set-based option: 或者您可以使用基于集合的选项:
Update oci Set oci.orderNumber = inserted.xml.value('(//*:OrderNumber)[1]', 'varchar(max)')
from [dbo].[dell.des.OCIMessages] oci join inserted on oci.id = inserted.id
What about this? 那这个呢?
You need a unser defined function to retrieve your value 您需要一个未定义的函数来检索您的值
CREATE FUNCTION dbo.GetOrderNumber(@xml xml)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN @xml.value('(//*:OrderNumber)[1]', 'varchar(max)');
END
CREATE TABLE dbo.Test(id INT, xml XML, OrderNumber AS dbo.GetOrderNumber(xml));
And this is how it works 这就是它的工作原理
declare @xml1 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>11111</v1:OrderNumber>
</v1:OrderStatus>';
declare @xml2 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>22222</v1:OrderNumber>
</v1:OrderStatus>';
declare @xml3 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>33333</v1:OrderNumber>
</v1:OrderStatus>';
insert into dbo.Test VALUES(1,@xml1),(2,@xml2);
select * from dbo.Test;
insert into dbo.Test select 3,@xml3;
select * from dbo.Test;
I place a second answer, because this is a completely differing approach: 我给出了第二个答案,因为这是一个完全不同的方法:
Create a normal table 创建一个普通表
CREATE TABLE dbo.Test(id INT, xml XML, OrderNumber VARCHAR(100));
CREATE TRIGGER dbo.InsertToTest ON dbo.Test
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO dbo.Test(id,xml,OrderNumber)
SELECT id,xml,xml.value('(//*:OrderNumber)[1]', 'varchar(max)')
FROM inserted
END
GO
And this is how it works 这就是它的工作原理
declare @xml1 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>11111</v1:OrderNumber>
</v1:OrderStatus>';
declare @xml2 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>22222</v1:OrderNumber>
</v1:OrderStatus>';
declare @xml3 xml=
'<v1:OrderStatus xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xmlns.dell.com/Services/DMT/OrderStatus/V1">
<v1:OrderNumber>33333</v1:OrderNumber>
</v1:OrderStatus>';
insert into dbo.Test VALUES(1,@xml1,'SomeValue'),(2,@xml2,'AnotherValue');
select * from dbo.Test;
insert into dbo.Test select 3,@xml3,null;
select * from dbo.Test;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.