根据Microsoft SQL Server 2005中是否存在行来更新或插入行

时间:2010-05-23 16:21:22

标签: sql sql-server-2005

我将XML文档作为Microsoft SQL Server 2005中存储过程的输入传递。 这是作为输入传递的示例XML

<Strategy StrategyID="0" TOStrategyID="8" ShutdownQtySell="1" ShutdownQtyBuy="1">
      <ParameterRange ParameterSetID="6" ParameterRangeID="1" ParameterRangeFrom="0" ParameterRangeTo="20" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="4" ParameterRangeFrom="21" ParameterRangeTo="40" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="5" ParameterRangeFrom="41" ParameterRangeTo="60" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="6" ParameterRangeFrom="61" ParameterRangeTo="80" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="7" ParameterRangeFrom="81" ParameterRangeTo="100" ParameterAutoTakeOut="False">
      </ParameterRange>
</Strategy>

我可以使用SQL Server中的OpenXML功能检索数据

我使用它来获取与ParameterRange行

对应的数据
SELECT ParameterRangeID as iRangeID,  
       ParameterSetID as iSetID,  
       ParameterRangeFrom as fRangeFrom,  
       ParameterRangeTo as fRangeTo,  
       ParameterAutoTakeOut as bTakeoutEnabled  
 FROM OPENXML(@idoc, '/Strategy/ParameterRange', 1)  
 WITH (ParameterSetID int,ParameterRangeID int,ParameterRangeFrom float,ParameterRangeTo float,ParameterAutoTakeOut bit)  

现在,我需要将这些行插入/更新到TempRanges表中,该表具有(iRangeID,iSetID)作为主键。
如果主键有一行,我想更新它的最新值,如果没有该主键的行,我需要插入表中。

如何在存储过程中完成此操作?

谢谢, 斯

1 个答案:

答案 0 :(得分:2)

您要实现的目标称为UPSERT。 SQL2008直接通过MERGE

支持此功能

对于SQL2005,您需要将其分为两个操作。一个UPDATE在键上使用INNER JOIN,一个INSERT使用OUTER JOIN作为额外记录。

SET NOCOUNT ON

IF (OBJECT_ID('tempdb..#TempRanges') IS NULL)
BEGIN
CREATE TABLE #TempRanges(
    [iRangeID] [int] NOT NULL,
    [iSetID] [int] NOT NULL,
    [fRangeFrom] [float] NOT NULL,
    [fRangeTo] [float] NOT NULL,
    [bTakeoutEnabled] [bit] NOT NULL,
 CONSTRAINT [PK_TempRanges] PRIMARY KEY CLUSTERED 
(
    [iRangeID] ASC,
    [iSetID] ASC
)
)
END
ELSE
BEGIN
DELETE FROM #TempRanges
INSERT INTO #TempRanges([iRangeID], [iSetID], [fRangeFrom], [fRangeTo], [bTakeoutEnabled])
SELECT '1', '6', '0', '20', '0' UNION ALL
SELECT '4', '6', '21', '40', '0' UNION ALL
SELECT '5', '6', '999', '60', '0' UNION ALL
SELECT '6', '6', '61', '80', '0' 
END



DECLARE @doc XML

SET @doc = '<Strategy StrategyID="0" TOStrategyID="8" ShutdownQtySell="1" ShutdownQtyBuy="1">
      <ParameterRange ParameterSetID="6" ParameterRangeID="1" ParameterRangeFrom="0" ParameterRangeTo="20" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="4" ParameterRangeFrom="21" ParameterRangeTo="40" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="5" ParameterRangeFrom="41" ParameterRangeTo="60" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="6" ParameterRangeFrom="61" ParameterRangeTo="80" ParameterAutoTakeOut="False">
      </ParameterRange>
      <ParameterRange ParameterSetID="6" ParameterRangeID="7" ParameterRangeFrom="81" ParameterRangeTo="100" ParameterAutoTakeOut="False">
      </ParameterRange>
</Strategy>'

DECLARE @idoc INT

EXEC sp_xml_preparedocument @idoc OUTPUT, @doc


UPDATE    #TempRanges
SET    fRangeFrom =ParameterRangeFrom, fRangeTo =ParameterRangeTo, bTakeoutEnabled =ParameterAutoTakeOut
FROM OPENXML(@idoc, '/Strategy/ParameterRange', 1)
WITH (ParameterSetID int,ParameterRangeID int,ParameterRangeFrom float,ParameterRangeTo float,ParameterAutoTakeOut bit)  AS input
INNER JOIN #TempRanges ON #TempRanges.iRangeID = input.ParameterRangeID AND #TempRanges.iSetID = input.ParameterSetID

PRINT CONVERT(VARCHAR(10) ,@@ROWCOUNT) + ' Updated'


INSERT INTO #TempRanges
           ([iRangeID]
           ,[iSetID]
           ,[fRangeFrom]
           ,[fRangeTo]
           ,[bTakeoutEnabled])
SELECT ParameterRangeID as iRangeID,  
       ParameterSetID as iSetID,  
       ParameterRangeFrom as fRangeFrom,  
       ParameterRangeTo as fRangeTo,  
       ParameterAutoTakeOut as bTakeoutEnabled  
FROM OPENXML(@idoc, '/Strategy/ParameterRange', 1)
WITH (ParameterSetID int,ParameterRangeID int,ParameterRangeFrom float,ParameterRangeTo float,ParameterAutoTakeOut bit)  AS input
LEFT OUTER JOIN #TempRanges ON #TempRanges.iRangeID = input.ParameterRangeID AND #TempRanges.iSetID = input.ParameterSetID
WHERE #TempRanges.iRangeID IS NULL


PRINT CONVERT(VARCHAR(10) ,@@ROWCOUNT) + ' Inserted'

SELECT * FROM #TempRanges