Вставьте значение с помощью оператора select или, если оно не существует, введите новое значение - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь выполнить запрос в SQL Server, где я обновляю строку и, если она не существует, создаю строку.Это прекрасно работает, но в моем операторе Insert для создания новой строки мне нужно выбрать значение из этой таблицы для _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, возвращаемых для учетной записи и года.

Если это январь, другие записи не будут сохранены, и я не вернул _idref.

В этом случае мне просто нужно заменить выбор на NEWID().

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Не уверен, является ли это отраслевым стандартом, но я называю этот тип операции "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. ;

Очевидно, это скорее общий подход. Ваш случай все еще применяется, хотя. Я бы запросил таблицу, чтобы увидеть, существует ли строка в первую очередь. Если это так, обновите его соответствующим образом. Если это не так, вставьте новый с новым идентификатором.

0 голосов
/ 13 ноября 2018

Как прокомментировал @ Felipe-Martins, оператор MERGE может немного упростить ситуацию.

MERGE явно не решает конкретный вопрос, который у вас был о динамическом повторном использовании существующего _idref или создании нового с помощью newid (), но это легко решить, обернув вызов 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
    ) 
...