Возможно моделировать функциональность mySQL ON DUPLICATE KEY UPDATE с SQL Server - PullRequest
9 голосов
/ 27 июля 2010

Я использую SQL Server 2008 и хотел бы иметь возможность использовать что-то вроде предложения mySQL ON DUPLICATE KEY UPDATE для INSERT операторов

Текущий унаследованный код выполняет удаление и последующую вставку, которые сталкиваются с проблемами параллелизма с дублированием вставок ключей из отдельных потоков:

Вот ошибка, которую я вижу в моей производственной среде:

Violation of PRIMARY KEY constraint 'PK_Audience'. Cannot insert duplicate key in object 'dbo.Audience'.

(sp_ContentUpdate)

Первичный ключ:

AudienceId, VersionId

Оскорбляющий SQL:

DELETE  FROM  dbo.Audience
WHERE   VersionId = @VersionId

IF  @AudienceXml IS NOT NULL
    BEGIN
    INSERT INTO dbo.Audience (
        VersionId,
        AudienceId,
        CreatedDate,
        CreatedByPersonId,
        )
    SELECT  @VersionId,
            AudienceId,
            GETUTCDATE(),
            @PersonId
                FROM    dbo.Audience
    JOIN    @AudienceXml.nodes('/Audiences/Audience') node(c)
    ON      Audience.AudienceName = c.value('@Name', 'nvarchar(50)')
    END

Заключение этого TSQL в транзакцию, по-видимому, либо устраняет проблему параллелизма, либо маскирует проблему путем изменения времени. Тем не менее, я не думаю, что завершение транзакции фактически решило параллелизм.

Возможно, я ошибаюсь. Ваши предложения приветствуются.

Ответы [ 2 ]

10 голосов
/ 27 июля 2010

Ну, Билл победил нас всех, но вот пример того, как это может выглядеть:

Merge dbo.Audience As target
Using   (
        Select @VersionId As VersionId, AudienceId, GetUtcDate() As CreatedDate, @PersonId As CreatedByPersonId
        From dbo.Audience
            Join @AudienceXml.nodes('/Audiences/Audience') node(c)
                On Audience.AudienceName = c.value('@Name', 'nvarchar(50)')
        )
When Matched Then
    Update 
    Set VersoinId = target.VersionId, Audience = target.AudienceId
        , CreatedDate = target.CreatedDate
        , CreatedByPersionId = target.CreatedByPersonId
When Not Matched Then
    Insert dbo.Audience(VersionId, AudienceId, CreatedDate, CreatedByPersonId)
8 голосов
/ 27 июля 2010

Вы должны прочитать о том, как использовать оператор MERGE в Microsoft SQL Server 2008. На самом деле это способ ANSI / ISO SQL для решения этой ситуации (ключ MySQL ON DUPLICATE - это собственный MySQLism).

См. Документы по MERGE заявлению в MSDN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...