SQL Server--Setting column value during insert using trigger

时间:2016-04-15 15:12:32

标签: sql sql-server xml triggers xquery

I have a table with the following columns:

id, xml, receivedDate, processed, processedDateTime, orderNumber

id, receivedDate, and processed all have default values.

The XML being stored in the xml column looks like this:

<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. 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.

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.

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!

3 个答案:

答案 0 :(得分:0)

您可以在更新中使用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

或者你可以使用基于集合的选项:

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

答案 1 :(得分:0)

这个怎么样?

您需要一个未定义的函数来检索您的值

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));

这就是它的工作原理

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;

答案 2 :(得分:0)

我给出了第二个答案,因为这是一个完全不同的方法:

创建普通表

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

创建&#34; INSTEAD OF&#34;触发

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;

这就是它的工作原理

{{1}}