我需要从表中提取记录,将数据复制到第二个表,然后更新第一个表中的记录,以表明它们已成功复制。
我目前的SP代码是:
SELECT TBL_ADDRESSBOOKADDRESSES.* FROM TBL_ADDRESSBOOKADDRESSES
INNER JOIN TBL_CAMPAIGNS
ON TBL_ADDRESSBOOKADDRESSES.adds_ABMId = TBL_CAMPAIGNS.campaign_AddressBook
WHERE TBL_CAMPAIGNS.campaign_Status = 1
现在执行上述操作后,我需要将此数据插入名为TBL_RECIPIENTS的第二个表中。假设这些列在TBL_ADDRESSBOOKADDRESSES中简单地命名为col_1,col_2,col_3 .... col_5,并且在TBL_RECIPIENTS中它们是相同的。
执行此操作后,我需要更新 TBL_CAMPAIGNS.campaign_Status = 2 理想情况下,这应仅适用于那些实际已更新的记录(如果脚本因服务器崩溃而中途停止等)
如果您需要澄清任何内容,请与我们联系。
非常感谢!
我已经采取了下面的建议,并提出下面的工作代码。我已阅读教程,建议添加try / catch以确保在发生任何错误时回滚。我的代码在这方面是否足够?
任何建议都会感激不尽。
感谢。
CREATE PROCEDURE web.SERVER_create_email_recipients
AS
BEGIN TRY
--sets (n) campaigns ready for transfer of emails to mailing list
UPDATE TOP(1) TBL_CAMPAIGNS
SET TBL_CAMPAIGNS.campaign_Status = 1
WHERE TBL_CAMPAIGNS.campaign_Status = 0
--finds above marked campaigns, retreives addresses then copies them to TBL_CAMPAIGNRECIPIENTS ready for auto mailout
INSERT TBL_CAMPAIGNRECIPIENTS (recip_CampaignId, recip_Email, recip_Forename, recip_Surname, recip_adds_Key)
SELECT C.Campaign_AddressBook, ABA.adds_Email, ABA.adds_RecipientForename, ABA.adds_RecipientSurname, ABA.adds_Key
FROM TBL_ADDRESSBOOKADDRESSES ABA
JOIN TBL_CAMPAIGNS C ON ABA.adds_ABMId = C.campaign_AddressBook
WHERE C.campaign_Status = 1
--checks that above emails have been copied across and then sets the campaigns status accordingly
UPDATE C
SET C.campaign_Status = 2
From TBL_CAMPAIGNS C
JOIN TBL_ADDRESSBOOKADDRESSES aba
ON aba.adds_ABMId = C.campaign_AddressBook
JOIN TBL_CAMPAIGNRECIPIENTS r on aba.adds_Key = r.recip_adds_Key
WHERE C.campaign_Status = 1
END TRY
BEGIN CATCH
-- Whoops, there was an error
IF @@TRANCOUNT > 0
ROLLBACK
-- Raise an error with the details of the exception
DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
SELECT @ErrMsg = ERROR_MESSAGE(),
@ErrSeverity = ERROR_SEVERITY()
--throws out error to logs?
RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH
答案 0 :(得分:4)
您是否考虑将所有内容都放在交易中?
实施例: DECLARE @ErrorCode INT
BEGIN TRAN
UPDATE Authors
SET Phone = '911'
WHERE au_id = 2
SELECT @ErrorCode = @@ERROR
IF (@intErrorCode <> 0) GOTO ErrExit
DELETE Authors WHERE Phone = '911' au_id <> 2
SELECT @ErrorCode = @@ERROR
IF @ErrorCode <> 0) GOTO ErrExit
COMMIT TRAN
ErrExit;
IF (@intErrorCode <> 0)
ROLLBACK TRAN
如果更新或删除错误,则将回滚事务。如果系统在提交之前崩溃,则sql server会进行回滚,因为存在未公开的事务
答案 1 :(得分:2)
我对你的结构做了一些猜测,连接可能不正确
INSERT TBL_RECIPIENTS (Col1, Col2, COl3)
SELECT ABA.Col1, ABA.Col2,ABA.Col3
FROM TBL_ADDRESSBOOKADDRESSES ABA
INNER JOIN TBL_CAMPAIGNS C ON ABA.adds_ABMId = C.campaign_AddressBook
WHERE TBL_CAMPAIGNS.campaign_Status = 1
UPDATE C
SET C.campaign_Status = 2
From TBL_CAMPAIGNS C
JOIN TBL_ADDRESSBOOKADDRESSES aba
on aba.adds_ABMId = C.campaign_AddressBook
JOIN TBL_RECIPIENTS r on aba.id = r.sameid
WHERE TBL_CAMPAIGNS.campaign_Status = 1
注意我没有使用select *,它永远不会在生产代码中使用。我还使用了别名来使代码更容易阅读。
答案 2 :(得分:1)
一种方法是使用OUTPUT
子句;在这种情况下,您可以选择已插入的所有地址簿ID,并使用它来更新广告系列。尽管如此,如果你想要获得可靠性,你真的需要使用交易,锁定会阻止更新和插入。
DECLARE @addressBookIds TABLE(AddressBookId INT NOT NULL)
INSERT INTO TBL_RECIPIENTS
OUTPUT INSERTED.adds_ABMId INTO @addressBookIds
SELECT TBL_ADDRESSBOOKADDRESSES.*
FROM TBL_ADDRESSBOOKADDRESSES
INNER JOIN TBL_CAMPAIGNS
ON TBL_ADDRESSBOOKADDRESSES.adds_ABMId = TBL_CAMPAIGNS.campaign_AddressBook
WHERE TBL_CAMPAIGNS.campaign_Status = 1
UPDATE TBL_CAMPAIGNS
SET [campaign_Status] = 2
FROM TBL_CAMPAIGNS
INNER JOIN @addressBookIds AS T
ON TBL_CAMPAIGNS.campaign_AddressBook = T.AddressBookId
AND TBL_CAMPAIGNS.campaign_Status = 1
如果广告系列ID是TBL_RECIPIENTS
表的一部分,那么您将100%确定您通过OUTPUT
子句获得了正确的广告系列ID,并且实际上并不需要锁定交易。据我所知,SQL Server不允许您在OUTPUT
子句中引用连接表中的列(与DELETE ... OUTPUT
和UPDATE ... OUTPUT
不同),因此广告系列ID 必须成为INSERT
的{{1}}子句的一部分。
由于广告系列ID不是输出的一部分,因此该解决方案几乎是HLGEM答案的复杂版本,但它可能对您有用。
答案 3 :(得分:0)
您应该将更新的地址id存储到使用INSERT的OUTPUT子句填充的表变量中:
create table TBL_ADDRESSBOOKADDRESSES (
adds_ABMID int identity(1,1) not null,
col_1 varchar(100),
col_2 varchar(100));
go
create table TBL_RECIPIENTS (
adds_ABMID int not null,
col_1 varchar(100),
col_2 varchar(100));
go
create table TBL_CAMPAIGNS (
campaign_AddressBook int,
campaign_Status int);
go
insert into TBL_ADDRESSBOOKADDRESSES (col_1, col_2)
values ('spam', 'is evil');
insert into TBL_ADDRESSBOOKADDRESSES (col_1, col_2)
values ('all mass mail', 'is spam');
insert into TBL_CAMPAIGNS (campaign_AddressBook, campaign_Status)
values (1,1);
insert into TBL_CAMPAIGNS (campaign_AddressBook, campaign_Status)
values (2,1);
go
set nocount on;
declare @newRecipients table (adds_ABMID int);
begin transaction
insert into TBL_RECIPIENTS (adds_ABMID, col_1, col_2)
output inserted.adds_ABMID into @newRecipients
SELECT a.adds_ABMID
, a.col_1
, a.col_2
FROM TBL_ADDRESSBOOKADDRESSES a
INNER JOIN TBL_CAMPAIGNS ON a.adds_ABMId = TBL_CAMPAIGNS.campaign_AddressBook
WHERE TBL_CAMPAIGNS.campaign_Status = 1
update TBL_CAMPAIGNS
set campaign_Status = 2
from TBL_CAMPAIGNS as c
join @newRecipients as new on c.campaign_AddressBook = new.adds_ABMID;
commit;
go
select * from TBL_RECIPIENTS;
select * from TBL_CAMPAIGNS;
go