我有一个具有这种结构的 XML 响应,但有大约 150 个不同的节点:
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order>
<OrderID>334</OrderID>
<AmountPaid currencyID="EUR">17.10</AmountPaid>
<UserID>marc58</UserID>
<ShippingAddress>
<Name>Marc Juppé</Name>
<Address>Rue</Address>
<City>Paris</City>
<StateOrProvince></StateOrProvince>
<Country>FR</Country>
<Phone>333333333</Phone>
<PostalCode>22222</PostalCode>
</ShippingAddress>
<ShippingCosts>4.50</ShippingCosts>
<Items>
<Item>
<Details>
<ItemID>3664</ItemID>
<Store>47</Store>
<Title>MCPU DDA010</Title>
<SKU>mmx</SKU>
</Details>
<Quantity>1</Quantity>
<Price currencyID="EUR">6.2</Price>
</Item>
<Item>
<Details>
<ItemID>3665</ItemID>
<Store>45</Store>
<Title>MCPU DFZ42</Title>
<SKU>mmy</SKU>
</Details>
<Quantity>2</Quantity>
<Price currencyID="EUR">3.2</Price>
</Item>
</Items>
</Order>
</Orders>
Run Code Online (Sandbox Code Playgroud)
我需要将此信息存储到 3 个不同的表中,对于Item
表,我需要为每个不同的表创建记录<Item>
,但还要插入订单节点的详细信息;像这样:
|ItemID|Store|Title |SKU|Quantity|Price|OrderID|AmountPaid|UserID|ShippingCost|
|3664 | 47|DDA010|mmx| 1| 6.2| 334| 17.10|marc58| 4.50|
|3665 | 45|DFZ42 |mmy| 2| 3.2| 334| 17.10|marc58| 4.50|
Run Code Online (Sandbox Code Playgroud)
为了在不同的表中“自动”写入所需的信息,我在社区的大力帮助下构建了这个查询: …
在表中Orders
,我存储了我们从所有商店收到的订单。由于一个订单可以有多个行,列中有OrderID
和OrderLineID
在那里OrderID
可以复制,但OrderLineID
必须是一个顺序中是唯一的。
由于订单可以修改,存储过程首先检查收到的订单OrderLineID
是否已经存在于表中,然后决定插入还是更新。为此,我们:
然后是主表:
IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID ......)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID
Run Code Online (Sandbox Code Playgroud)
或者该MERGE
功能是否提供更好的性能/控制?
但问题如下:
由于线路问题/服务器繁忙等,Order
消息(或修改)可能会被多次发送,我们不知道按哪个顺序发送。因此,为了避免Order
修改后到达,从而覆盖修改,我们添加了一个时间列:
IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID AND LastModified<@CreatedTime
Run Code Online (Sandbox Code Playgroud)
这样,如果后一条消息比前一条消息旧,则对表没有影响。
但是,消息及其修改可能会在很短的时间内发送两次(或更多),以至于后一条消息在保存前一条消息之前到达。因此,对于存储过程的两次执行,它 …
我需要正确格式化一些欧洲地址。其中一个步骤是将第一个字母大写,但要避免一些特定的词,例如“on”、“on”、“von”、“van”、“di”、“in”、“sul”。因此,虽然我的技能稀缺,但我认为使用基于 RegEx 的函数是个好主意。
经过一番谷歌搜索后,我在这里找到了这个:
CREATE FUNCTION InitialCap
(
@String nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @Position INT;
SELECT
@String = STUFF(LOWER(@String),1,1,UPPER(LEFT(@String,1))) COLLATE Latin1_General_Bin,
@Position = PATINDEX('%[^A-Za-z][a-z]%',@String COLLATE Latin1_General_Bin);
WHILE @Position > 0
SELECT
@String = STUFF(@String,@Position,2,UPPER(SUBSTRING(@String,@Position,2))) COLLATE Latin1_General_Bin,
@Position = PATINDEX('%[^A-Za-z][a-z]%',@String COLLATE Latin1_General_Bin);
RETURN @String;
END
Run Code Online (Sandbox Code Playgroud)
这似乎是在寻找一个“非字母”+一个小写“字母”的序列
[^A-Za-z][a-z]
Run Code Online (Sandbox Code Playgroud)
好的,我想我已经了解它是如何工作的,并且我对其进行了修改以最好地满足我的需求。
我认为最好搜索一个空格或 ' 或 - 和一个小写字母,因此我将其更改为
[\s'-][\w]
Run Code Online (Sandbox Code Playgroud)
然后,经过多次尝试,我在 regexr.com 上构建了这个 RegEx,它似乎捕获了所需的序列:
[\s](?!di\s|in\s|sul\s|on\s|upon\s|von\s|uber\s|ueber\s)[\w]
Run Code Online (Sandbox Code Playgroud)
但是当我把它放到上面的函数中时,结果并不像预期的那样。
怎么了?
使用 Forrest 的这个解决方案:
DECLARE @XML xml =
'<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order>
<OrderID>334</OrderID>
<AmountPaid currencyID="EUR">17.10</AmountPaid>
<UserID>marc58</UserID>
<ShippingAddress>
<Name>Marc Juppé</Name>
<Address>Rue garçonneé III° arrondissement</Address>
<City>Paris</City>
<StateOrProvince></StateOrProvince>
<Country>FR</Country>
<Phone>333333333</Phone>
<PostalCode>22222</PostalCode>
</ShippingAddress>
<ShippingCosts>4.50</ShippingCosts>
<Items>
<Item>
<Details>
<ItemID>3664</ItemID>
<Store>47</Store>
<Title>MCPU DDA010</Title>
<SKU>mmx</SKU>
</Details>
<Quantity>1</Quantity>
<Price currencyID="EUR">6.2</Price>
</Item>
<Item>
<Details>
<ItemID>3665</ItemID>
<Store>45</Store>
<Title>MCPU DFZ42</Title>
<SKU>mmy</SKU>
</Details>
<Quantity>2</Quantity>
<Price currencyID="EUR">3.2</Price>
</Item>
</Items>
</Order>
</Orders>'
SELECT
x.value('./ItemID[1]','int') AS ItemID,
x.value('./Store[1]','int') AS Store,
x.value('./Title[1]','nvarchar(100)') AS Title,
x.value('./SKU[1]','nvarchar(100)') AS SKU,
x.value('../Quantity[1]','int') AS Qty,
x.value('../Price[1]','decimal(11,2)') AS Price,
x.query('//OrderID[1]').value('.','int') AS OrderID, …
Run Code Online (Sandbox Code Playgroud)