gpt4 book ai didi

sql-server - 基于动态XML的插入/更新

转载 作者:行者123 更新时间:2023-12-03 16:40:29 24 4
gpt4 key购买 nike

我有以下XML:

<NewDataSet>
<Data>
<Id>560f05b2-b215-4fea-9ac6-7f012fbca331</Id>
<Number>384D25334E04593B6DE9955E72F413F8A0A828FF</Number>
<CurrentDate>2012-11-21T09:09:26+00:00</CurrentDate>
</Data>
<Data>
<Id>9cff574b-59ea-4cbd-a2db-9ed02b6cc602</Id>
<Number>384D25334E04593B6DE9955E72F413F8A0A828FF</Number>
<Location>Town</Location>
<CurrentDate>2012-11-21T09:09:53+00:00</CurrentDate>
</Data>
</NewDataSet>


我正在尝试编写一个查询,该查询将基于给定的xml插入新记录或更新现有记录。问题是我不能使用预定义的列名,因为表结构有时会改变。因此,该想法是生成动态查询并应用它。到目前为止,我有以下内容:

    SET NOCOUNT OFF;


DECLARE @TableName nvarchar(50)
DECLARE @TableData xml
DECLARE @Query nvarchar(max)
DECLARE @Id uniqueidentifier
DECLARE @CurrentDate datetime

-- declare cursor
DECLARE cursor_inserting CURSOR LOCAL FAST_FORWARD FOR
SELECT
r.value('fn:local-name(.)', 'nvarchar(50)'),
r.query('.')
FROM @Data.nodes('//NewDataSet/*') AS records(r)
ORDER BY r.value('fn:local-name(.)', 'nvarchar(50)')

-- open cursor
OPEN cursor_inserting
FETCH NEXT FROM cursor_inserting INTO @TableName, @TableData

WHILE @@FETCH_STATUS = 0
BEGIN

-- Get id
SELECT @Id = o.value('Id[1]', 'uniqueidentifier') FROM @TableData.nodes('*') as n(o)
SELECT @CurrentDate = o.value('CurrentDate[1]', 'datetime') FROM @TableData.nodes('*') as n(o)

SET @Query = NULL

-- temporary update query
SET @UpdateTemp = NULL
SELECT @UpdateTemp = COALESCE(@UpdateTemp + ', ', '') + o.value('fn:local-name(.)', 'nvarchar(50)') + ' = ''' + CAST(o.query('text()') as nvarchar(4000)) + '''' FROM @TableData.nodes('/*/*') as n(o)
SET @UpdateTemp = 'UPDATE ' + @TableName + ' SET ' + @UpdateTemp + ' WHERE Id = ''' + CAST(@Id as nvarchar(40)) + ''''

-- temporary insert query
SET @Insert1Temp = NULL
SELECT @Insert1Temp = COALESCE(@Insert1Temp + ', ', '') + o.value('fn:local-name(.)', 'nvarchar(50)') FROM @TableData.nodes('/*/*') as n(o)

SET @Insert2Temp = NULL
SELECT @Insert2Temp = COALESCE(@Insert2Temp + ', ', '') + '''' + CAST(o.query('text()') as nvarchar(4000)) + '''' FROM @TableData.nodes('/*/*') as n(o)

SET @InsertTemp = 'INSERT INTO ' + @TableName + ' ( ' + @Insert1Temp + ' ) VALUES ( ' + @Insert2Temp + ' )'

IF @TableName = 'Data'
BEGIN

IF EXISTS (SELECT * FROM Data WHERE Id = @Id)
BEGIN

IF EXISTS (SELECT * FROM tblAudit WHERE Id = @Id AND CurrentDate < @CurrentDate)
BEGIN
SET @Query = @UpdateTemp
END

END
ELSE
BEGIN
SET @Query = @InsertTemp
END
END

IF @Query IS NOT NULL
BEGIN
SELECT @Query
EXEC (@Query)
END
END
FETCH NEXT FROM cursor_inserting INTO @TableName, @TableData
END

CLOSE cursor_inserting
DEALLOCATE cursor_inserting


如果我想知道有什么更好的方法可以在SQL内部实现,我知道我可以在我的应用程序代码中在SQL外部完成此操作,但是我希望将其放在存储过程中的某个位置以提供xml,并且需要采取的行动。

更新1

我想澄清一下,我的主要问题是基于XML的查询正确生成。很高兴看到处理instert / update的不同方法,但作为补充

更新2

xml中可以有多个表。例如。不仅是数据,还有数据2

更新3

我已经更新了现在的内容-现在可以生成正确的插入/更新,但是现在转换存在问题。例如。日期字符串为xml格式,而sql不想自动将其转换。所以我的下一步是从数据库中获取正确的列类型,而不是直接从xml中生成查询instert。我希望这会起作用。

最佳答案

是。

您可以使用MERGE和SQL XQuery在一条语句中执行此操作。

就像是...

merge Data as target
using
(
select
x.q.value('Id[1]','uniqueidentifier') as ID,
x.q.value('Number[1]','varchar(50)') as Number,
x.q.value('Location[1]','varchar(50)') as Town,
x.q.value('CurrentDate[1]','datetime') as CurrentDate
from
@TableData.nodes('/NewDataSet/Data')x(q)
) as Source (ID,Number,Town,CurrentDate)
on target.id=source.id
when matched and target.CurrentDate < source.CurrentDate then
update set
Number = source.number,
town = source.town,
currentdate = source.currentdate
when not matched then
insert (ID,number,town,currentdate)
values (source.id,source.number,source.town,source.currentdate);

关于sql-server - 基于动态XML的插入/更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13585172/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com