我想插入使用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
答案 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 question和the official MSDN article。
您必须使用ALTER INDEX添加此属性,或者(如果唯一约束在主键上)删除并重新创建它。
一旦到位,任何插入都应该只拒绝无效行而不是整批。
答案 3 :(得分:0)
可以使用SET XACT_ABORT OFF(ON) - more here 来控制转换的行为。