我从其中一个存储过程中获取的一条SQL命令一直遇到一些奇怪的行为。
此命令遵循以下执行顺序:
1)放置表格
2)从实时服务器的表名称中选择*
3)修改表以应用PK-此步骤在4次每日执行中一次失败
我的SQL语句:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'
[inf].[tblBase_MyTable]') AND type in (N'U'))
DROP TABLE [inf].[tblBase_MyTable]
SELECT * INTO [inf].[tblBase_MyTable]
FROM LiveServer.KMS_ALLOCATION WITH (NOLOCK)
ALTER TABLE [inf].[tblBase_MyTable] ADD
CONSTRAINT [PK_KMS_ALLOCATION] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY =
OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GRANT SELECT ON [inf].[tblBase_MyTable] TO ourGroup
考虑到表已删除,这很奇怪,我认为索引/键也会被删除。但是我每天都在同一时间收到此错误。任何建议将不胜感激。
错误:
CREATE UNIQUE INDEX语句终止,因为找到对象名称“ inf.tblBase_MyTable”和索引名称“ PK_KMS_ALLOCATION”的重复键。
答案 0 :(得分:2)
许多人认为NOLOCK正在做什么
大多数人认为NOLOCK提示只是读取行而不必 等到其他人提交了更新或选择。如果有人 正在更新,没关系。如果他们更改了值,则占99.999% 他们提交的时间,因此可以在提交之前先阅读一下。 如果他们还没有更改记录,那么可以节省我的等待时间, 就像我的交易发生在他们的交易之前一样。
问题
问题在于事务不只是更新行。经常 他们需要更新索引,或者它们的空间不足 数据页。这可能需要分配新页面和现有行 在要移动的页面上,称为PageSplit。有可能为您 选择完全错过一些行和/或计算其他行 两次。
答案 1 :(得分:0)
好吧...您可能必须重复创建新表并填充它,直到@DarkoMartinovic的检查查询不返回重复项。只有这样,您才能继续添加PK。但是此解决方案可能会给您的实时系统带来沉重的负担。而且,您无法保证您也拥有1:1的数据副本。
答案 2 :(得分:0)
在这里回顾了各种有用的评论后,我决定(暂时)实施SNAPSHOT隔离,因为此接口未使用适当的暂存环境。
要转到此位置,将意味着要么创建一个暂存区并将该数据库设置为READ COMMITTED SNAPSHOT隔离,然后重新构建整个接口。
为此,在节省开发时间的基础上,我们选择确保在应用PK之前,处理任何可能从源头带走重复数据的虚假读取。
从目标服务器的性能来看,这绝不是理想的解决方案,但现在会提供一些空间,并且肯定会消除以前的错误。
下面的SQL方法:
DECLARE @ALLOCTABLE TABLE
(SEQ INT, ID NVARCHAR(1000), CLASSID NVARCHAR(1000), [VERSION] NVARCHAR(25), [TYPE]
NVARCHAR(100), VERSIONSEQUENCE NVARCHAR(100), VERSIONSEQUENCE_TO NVARCHAR(100),
BRANCHID NVARCHAR(100), ISDELETED INT, RESOURCE_CLASS NVARCHAR(25), RESOURCE_ID
NVARCHAR(100), WARD_ID NVARCHAR(100), ISCOMPLETE INT, TASK_ID NVARCHAR(100));
------- ALLOCATION
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[inf].
[tblBase_MyTable]') AND type in (N'U'))
DROP TABLE [inf].[tblBase_MyTable]
SELECT * INTO [inf].[tblBase_MyTable]
FROM LiveServer.KMS_ALLOCATION WITH (NOLOCK)
INSERT INTO @ALLOCTABLE
SELECT *
FROM
(SELECT
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ISCOMPLETE DESC) SEQ, AL.*
FROM [inf].[tblBase_MyTable] AL
)DUPS
WHERE SEQ >1
DELETE FROM [inf].[tblBase_MyTable]
WHERE ID IN (SELECT ID FROM @ALLOCTABLE)
AND ISCOMPLETE = 0
ALTER TABLE [inf].[tblBase_MyTable] ADD CONSTRAINT
[PK_KMS_ALLOCATION] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GRANT SELECT ON [inf].[tblBase_MyTable] TO OurGroup
答案 3 :(得分:-1)
由于您非常确定没有重复项,因此,在创建PK之前(列ID允许为NULL还是不允许为NULL),请您检查一下另一个问题。如果允许使用NULL,则在将列ID设置为NOT NULL后尝试创建PK。 SQL Server不允许在允许NULL的列上创建PK。