我正在尝试在SQL Server中执行查询,在其中更新一行,如果该行不存在,请创建一行。效果很好,但是在我用于创建新行的插入语句中,我需要从该表中为_idref uniqueidentifier
选择一个值。
我遇到的情况是,如果选择没有返回任何可能的值,我需要使用NEWID()
添加一个新的唯一标识符。
这是我的查询:
DECLARE @LGRACT BIGINT
DECLARE @SUBACT BIGINT
DECLARE @AMOUNT DECIMAL(12,2)
DECLARE @PostYear SMALLINT
DECLARE @PostMonth TINYINT
SET @PostYear = 2018
SET @PostMonth = 12
SET @LGRACT = 6000
SET @SUBACT = 200
SET @AMOUNT = 2000.00
UPDATE [Services Copy].dbo.lgrbal
SET balance = ((SELECT balance
FROM [Services Copy].dbo.lgrbal
WHERE lgract = @LGRACT
AND postyr = @PostYear
AND actprd = @PostMonth) + @AMOUNT)
WHERE lgract = @LGRACT
AND postyr = @PostYear
AND actprd = @PostMonth
IF @@ROWCOUNT = 0
INSERT INTO [Services Copy].dbo.lgrbal (_idnum, _idref, lgract, postyr, actprd, balance)
VALUES (NEWID(),
(SELECT TOP 1 _idref
FROM [Services Copy].dbo.lgrbal
WHERE lgract = @LGRACT
AND postyr = @PostYear)
WHERE NOT EXISTS NEWID()),
@LGRACT, @PostYear, @PostMonth, @AMOUNT)
您可以在INSERT INTO VALUES
部分中看到,我正在为返回的帐户和年份的select top 1
做_idref
。
如果是1月,将不会存储其他记录,也不会返回_idref
。
在这种情况下,我只需要用NEWID()
替换选择即可。
答案 0 :(得分:1)
正如@ Felipe-Martins所评论的那样,MERGE语句可能会使事情变得容易一些。
MERGE不能明确解决您关于动态重用现有_idref或通过newid()生成新的_idref的特定问题,但是可以通过在子查询周围包装isnull()
调用来轻松解决。
可能有一个更好的解决方案,但是自您发布以来的第一个小时,活动并没有太多,因此我认为我会保存该帖子,而不是丢弃它以防万一。
declare @LGRACT bigint
declare @SUBACT bigint
declare @AMOUNT decimal(12,2)
declare @PostYear smallint
declare @PostMonth tinyint
set @PostYear=2018
set @PostMonth=12
set @LGRACT = 6000
set @SUBACT = 200
set @AMOUNT = 2000.00
MERGE [Services Copy].dbo.lgrbal AS target
USING (SELECT @LGRACT, @AMOUNT, @PostYear, @PostMonth) AS source
(lgract, amount, postyr, actprd)
ON (
target.lgract = source.lgract and
target.postyr = source.postyr and
target.actprd = source.actprd
)
WHEN MATCHED THEN
UPDATE SET target.Balance = target.Balance + source.amount
WHEN NOT MATCHED THEN
INSERT (
_idnum,
_idref,
lgract,
postyr,
actprd,
balnce
)
VALUES (
newid(),
isnull(
(select top 1 _idref
from [Services Copy].dbo.lgrbal
where lgract=@LGRACT and postyr=@PostYear),
newid()),
source.lgract,
source.postyr,
source.actprd,
source.balance
)
答案 1 :(得分:0)
不确定这是否是行业标准,但是我将这种类型的操作称为“ Upsert”。
这是我在存储过程中处理该问题的典型方式。
IF (EXISTS(SELECT * FROM TABLE_NAME WHERE IdColumn = @IdParameter)) BEGIN
-- UPDATE
UPDATE TABLE_NAME
SET columns appropriately
WHERE IdColumn = @IdParameter
END
ELSE
BEGIN
-- INSERT
SET @IdParameter= NEWID();
INSERT INTO TABLE_NAME
SELECT @IdParameter,
@OtherParams
END
EXEC usp_Select_YourObject @IdParameter; -- other stored proc that handles the object to be returned. ;
显然,这更是一种通用方法。您的情况仍然适用。我将查询表以查看该行是否首先存在。如果是这样,请相应地对其进行更新。如果不是,请插入具有新ID的新ID。