Отключить неявные транзакции - PullRequest
2 голосов
/ 26 октября 2010

Я хотел бы сделать вставку в использование select, но я знаю, что некоторые строки могут потерпеть неудачу (что ожидается).Есть ли способ изменить неявные транзакции SQL Server 2008 так, чтобы те, которые не были выполнены, не откатывались?

-- get the count of the customers to send the sms to
SELECT @count = COUNT(*)
FROM PreCampaignCustomer
WHERE Processed = 0 AND CampaignID = @campaignid 
AND ErrorCount < 5

WHILE (@count > 0)
BEGIN
    DECLARE @customerid INT,
            @carrierid INT,
            @merchantcustomerid INT,
            @smsnumber NVARCHAR(50),
            @couponcode NVARCHAR(20)

    SELECT TOP 1 @customerid = pcc.CustomerID, @merchantcustomerid = pcc.MerchantCustomerID,
    @carrierid = c.CarrierID, @smsnumber = c.SMSNumber 
    FROM PreCampaignCustomer pcc
    INNER JOIN Customer c ON c.ID = pcc.CustomerID
    WHERE pcc.Processed = 0 AND pcc.CampaignID = @campaignid
    AND pcc.ErrorCount < 5
    ORDER BY pcc.ErrorCount

    --set the couponcode    
    IF @couponlength = -1 
    BEGIN
        SET @couponcode = 'NOCOUPON'
    END
    ELSE
    BEGIN
        EXEC [GenerateCouponCode]
        @length = 9,
        @couponcode = @couponcode OUTPUT
    END

    BEGIN TRY
        --use try/catch just in case the coupon code is repeated or any other error

        --Set the coupon text
        DECLARE @coupontext NVARCHAR(200),
                @smsrequestxml XML


        IF @coupontypecode = 1 --NONE
        BEGIN 
            SET @coupontext = @merchantname + ': ' + @smsmessage + ', Use Code: ' + dbo.FormatCouponCode(@couponcode, @couponcodegrouping) + '. Reply STOP to quit'
        END
        ELSE
        BEGIN
            SET @coupontext = @merchantname + ': ' + @smsmessage + '. Reply STOP to quit'
        END

        EXEC GetSMSRequest @config = @smsconfig, 
                    @smsType = 1, --Submit
                    @address = @smsnumber,
                    @carrierID = @carrierid,
                    @message = @coupontext,
                    @xml = @smsrequestxml OUTPUT

        BEGIN TRAN
            --create the CampaignCustomer record
            INSERT INTO CampaignCustomer
            (CampaignID, CustomerID, CouponCode, Active)
            VALUES
            (@campaignid, @customerid, @couponcode, 1)

            --Add the record to the queue
            INSERT INTO SMSQueue
            (CarrierID, [Address], [Message], TimeToSend, RequestXML, QueueID, HTTPStatusCode, Retries)
            VALUES
            (@carrierid, @smsnumber, @coupontext, @timetosend, @smsrequestxml, @queueid, 0, 0)

            --Create Outgoing SMS Log
            INSERT INTO SMSOutgoingLog
            (MerchantID, MerchantGroupID, MessageTypeCode, CreatedDate, Active)
            VALUES 
            (@merchantid, @merchantgroupid, @messagetypecode, GETDATE(), 1)

            --Update the LastSentSMSTime of the MerchantCustomer
            UPDATE MerchantCustomer
            SET LastSentSMS = GETDATE(),
            ModifiedDate = GETDATE()
            WHERE ID = @merchantcustomerid

            UPDATE PreCampaignCustomer
            SET Processed = 1,
            ModifiedDate = GETDATE()
            WHERE CustomerID = @customerid 
            AND CampaignID = @campaignid
        COMMIT TRAN
    END TRY
    BEGIN CATCH
        ROLLBACK TRAN

        -- Set the error
        UPDATE PreCampaignCustomer
        SET ErrorCount = ErrorCount + 1,
        ModifiedDate = GETDATE(),
        ErrorMessage = ERROR_MESSAGE(),
        ErrorNumber = ERROR_NUMBER()
        WHERE CustomerID = @customerid 
        AND CampaignID = @campaignid
    END CATCH

    SELECT @count = COUNT(*)
    FROM PreCampaignCustomer
    WHERE Processed = 0 AND CampaignID = @campaignid 
    AND ErrorCount < 5
END

Ответы [ 4 ]

2 голосов
/ 26 октября 2010

нет, INSERT - это одна команда. Транзакции определяют, как несколько команд объединяются в единые единицы работы, а не как строки объединяются в одной команде. Вы не можете иметь несколько строк INSERT и те, которые терпят неудачу (некоторые проблемы с ограничениями) и просто игнорируются. если какие-либо строки терпят неудачу, тогда вся INSERT терпит неудачу.

почему бы не попробовать изменить SELECT, чтобы исключить строки, которые потерпят неудачу?

что-то вроде:

INSERT INTO YourTable
        (col1, col2, col3)
    SELECT
        colA, colB, ColC
        FROM YourOtherTable
        WHERE ColA NOT IN (SELECT col1 FROM YourTable)
1 голос
/ 27 октября 2010

Возможно, вы думаете о свойстве IGNORE_DUP_KEY уникального индекса.

См. этот связанный вопрос SO и официальную статью MSDN на IGNORE_DUP_KEY.

Вам придется либо использовать ALTER INDEX, чтобы добавить это свойство, либо (если уникальное ограничение на первичный ключ) удалить и заново создать его.

Как только это будет сделано, любые вставки должны отклонять только недопустимые строки вместо всего пакета.

1 голос
/ 26 октября 2010

Думая «из коробки», если вы используете для этого SSIS, вы можете отправлять ошибочные строки по другому пути или просто выбрасывать их.

0 голосов
/ 26 октября 2010

Можно управлять поведением транзакций, используя SET XACT_ABORT OFF (ON) - подробнее здесь .

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