使用 SSMS 运行以下 UPDATE 命令,我得到返回消息说 1 行受影响。但是如果我随后使用 Select 进行跟踪,它会显示该行从未更新过。
此问题发生在 SSMS 和我使用实体框架在 C# 中构建的自定义应用程序中。从那以后,我停止使用实体框架生成的代码并直接转到存储过程。执行相同任务的所有 3 种不同方式我随机得到这个问题。有时可能需要 100 或 1000 次更新才能再次出现问题,也可能是几次更新后再次出现。
我运行了 UPDATE STATISTICS
,我重建了索引并重新组织了索引。
作为旁注,我从来没有遇到过仅插入更新的问题,我们从不删除任何记录。表上的总记录数为 201,741
UPDATE CreativeWorkFlowQueue
SET CurrentIndicator = 'N'
WHERE CreativeWorkFlowQueueId = 198231
SELECT *
FROM CreativeWorkFlowQueue
WHERE CreativeWorkFlowQueueId = 198231
这是表
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[CreativeWorkFlowQueue]
(
[CreativeWorkFlowQueueId] [int] IDENTITY(1,1) NOT NULL,
[DigitalCampaignCreativeId] [int] NOT NULL,
[WorkFlowQueueId] [int] NOT NULL,
[CurrentIndicator] [char](1) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[LastUpdatedDate] [datetime] NOT NULL,
[IsDeleted] [bit] NOT NULL,
PRIMARY KEY CLUSTERED ([CreativeWorkFlowQueueId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue]
ADD CONSTRAINT [CreateDate defaults to utcDate on CreativeWorkFlowQueue]
DEFAULT (GETUTCDATE()) FOR [CreateDate]
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue]
ADD CONSTRAINT [LastUpdatedDate defaults to utcDate on CreativeWorkFlowQueue]
DEFAULT (GETUTCDATE()) FOR [LastUpdatedDate]
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue]
ADD CONSTRAINT [DF_CreativeWorkFlowQueue_IsDeleted]
DEFAULT ((0)) FOR [IsDeleted]
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue] WITH CHECK
ADD CONSTRAINT [CreativeWorkFlowQueue DigitalCampaignCreativeId fk]
FOREIGN KEY([DigitalCampaignCreativeId])
REFERENCES [dbo].[DigitalCampaignCreative] ([DigitalCampaignCreativeId])
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue] CHECK CONSTRAINT [CreativeWorkFlowQueue DigitalCampaignCreativeId fk]
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue] WITH CHECK
ADD CONSTRAINT [CreativeWorkFlowQueue WorkFlowQueueId fk]
FOREIGN KEY([WorkFlowQueueId])
REFERENCES [dbo].[WorkFlowQueue] ([WorkFlowQueueId])
GO
ALTER TABLE [dbo].[CreativeWorkFlowQueue] CHECK CONSTRAINT [CreativeWorkFlowQueue WorkFlowQueueId fk]
GO
EDIT 添加也有同样问题的存储过程:
我没有包含这个存储过程仅仅是因为它很复杂,如果一个简单的更新不起作用,我想先从那里开始。
CREATE PROCEDURE [dbo].[sp_WtvToRtl]
@tbl DCCIdList READONLY,
@WorkFlowQueueId int
AS
BEGIN
SET NOCOUNT ON;
DECLARE @dccList TABLE (
CreativeWorkflowQueueId int null,
DigitalCampaignCreativeId int null,
WorkFlowQueueId int null,
CurrentIndicator varchar(1) collate SQL_Latin1_General_CP1_CI_AS null,
LastUpdatedDate datetime null
)
DECLARE @DCIDList TABLE(
DigitalCampaignCreativeId int null
)
DECLARE @res TABLE (
MergeAction VARCHAR(50) collate SQL_Latin1_General_CP1_CI_AS ,
CreativeWorkFlowQueueId INT,
_Position INT
)
BEGIN TRANSACTION t1
BEGIN TRY
INSERT INTO @dccList (CreativeWorkflowQueueId, DigitalCampaignCreativeId,LastUpdatedDate,WorkFlowQueueId,CurrentIndicator)
select CreativeWorkflowQueueId, DigitalCampaignCreativeId,LastUpdatedDate,WorkFlowQueueId, 'N' as CurrentIndicator from
dbo.CreativeWorkFlowQueue Where CurrentIndicator = 'Y'
and IsDeleted = 0
and DigitalCampaignCreativeId In
(SELECT DigitalCampaignCreativeId FROM VRF.DigitalCampaignCreative
WHERE IsDeleted = 0 and SfClosed = 0
and DccId in (Select DccId COLLATE SQL_Latin1_General_CP1_CI_AS from @tbl)
)
INSERT INTO @DCIDList
SELECT DigitalCampaignCreativeId FROM @dccList
GROUP BY DigitalCampaignCreativeId
INSERT INTO @dccList (DigitalCampaignCreativeId,WorkFlowQueueId,CurrentIndicator)
select DigitalCampaignCreativeId, @WorkFlowQueueId as WorkFlowQueueId, 'Y' as CurrentIndicator from
@DCIDList
MERGE vrf.CreativeWorkFlowQueue a
USING
(
SELECT
x.CreativeWorkflowQueueId,
x.DigitalCampaignCreativeId,
x.LastUpdatedDate,
x.WorkFlowQueueId,
x.CurrentIndicator
FROM @dccList x
) stg
ON stg.CreativeWorkflowQueueId = a.CreativeWorkflowQueueId
WHEN MATCHED THEN
UPDATE SET
a.CurrentIndicator = stg.CurrentIndicator,
a.LastUpdatedDate = getutcdate()
WHEN NOT MATCHED THEN
INSERT
(
CurrentIndicator,
DigitalCampaignCreativeId,
WorkFlowQueueId
)
VALUES
(
stg.CurrentIndicator,
stg.DigitalCampaignCreativeId,
stg.WorkFlowQueueId
)
-- ********************************************************************
-- Remove this if you don't need to return the results below.
OUTPUT
INSERTED.CreativeWorkFlowQueueId,
$action
INTO @res (CreativeWorkFlowQueueId, MergeAction);
-- ********************************************************************
COMMIT TRANSACTION t1
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(MAX), @ErrorSeverity INT, @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE() + ' Line ' + CAST(ERROR_LINE() AS NVARCHAR(5)), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
ROLLBACK TRANSACTION t1
--RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
SELECT 'FAILED' MergeAction,
s.CreativeWorkflowQueueId,
s.DigitalCampaignCreativeId,
'' DccId,
s.WorkFlowQueueId,
s.CurrentIndicator,
null CreateDate,
null LastUpdatedDate,
null IsDeleted,
@ErrorMessage ErrorMessage
FROM @dccList s
END CATCH
-- Normally, I would not have this. But this will simulate
-- what EF does if you need it.
SELECT
r.MergeAction,
a.CreativeWorkFlowQueueId,
a.DigitalCampaignCreativeId,
d.DccId,
a.WorkFlowQueueId,
a.CurrentIndicator,
a.CreateDate,
a.LastUpdatedDate,
a.IsDeleted,
'' ErrorMessage
FROM vrf.CreativeWorkFlowQueue a
JOIN @res r ON a.CreativeWorkFlowQueueId = r.CreativeWorkFlowQueueId
JOIN vrf.DigitalCampaignCreative d ON a.DigitalCampaignCreativeId = d.DigitalCampaignCreativeId
ORDER BY
r.MergeAction,
r._Position
END
用户定义的表类型是这样的:
CREATE TYPE [dbo].[DCCIdList] AS TABLE(
[DccId] [nvarchar](18) NULL
)