关闭隐式事务

时间:2010-10-26 14:17:49

标签: sql-server sql-server-2008

我想插入使用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 个答案:

答案 0 :(得分:2)

不,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 :(得分:1)

开箱即用,如果您使用SSIS执行此操作,您可以将失败的行发送到不同的路径或将其丢弃。

答案 2 :(得分:1)

您可能正在考虑唯一索引的IGNORE_DUP_KEY属性。

请参阅IGNORE_DUP_KEY上的this related SO questionthe official MSDN article

您必须使用ALTER INDEX添加此属性,或者(如果唯一约束在主键上)删除并重新创建它。

一旦到位,任何插入都应该只拒绝无效行而不是整批。

答案 3 :(得分:0)

可以使用SET XACT_ABORT OFF(ON) - more here 来控制转换的行为。