【发布时间】:2016-01-08 09:00:23
【问题描述】:
我的查询:
INSERT into PriceListRows (PriceListChapterId,[No])
SELECT TOP 250 100943 ,N'2'
FROM #AnyTable
此查询工作正常,并根据需要引发以下异常:
INSERT 语句与 CHECK 约束冲突 “CK_PriceListRows_RowNo_Is_Not_Unqiue_In_PriceList”。冲突 发生在数据库“TadkarWeb”、表“dbo.PriceListRows”中。
但是将SELECT TOP 250 更改为SELECT TOP 251(是的!只是将250 更改为251!)查询成功运行,没有任何检查约束异常!
为什么会有这种奇怪的行为?
注意事项:
我的检查约束是一个检查某种唯一性的函数。它查询大约 4 个表。
我检查了 SQL Server 2012 SP2 和 SQL Server 2014 SP1
** 编辑 1 **
检查约束函数:
ALTER FUNCTION [dbo].[CheckPriceListRows_UniqueNo] (
@rowNo nvarchar(50),
@rowId int,
@priceListChapterId int,
@projectId int)
RETURNS bit
AS
BEGIN
IF EXISTS (SELECT 1
FROM RowInfsView
WHERE PriceListId = (SELECT PriceListId
FROM ChapterInfoView
WHERE Id = @priceListChapterId)
AND (@rowID IS NULL OR Id <> @rowId)
AND No = @rowNo
AND (@projectId IS NULL OR
(ProjectId IS NULL OR ProjectId = @projectId)))
RETURN 0 -- Error
--It is ok!
RETURN 1
END
** 编辑 2 ** 检查约束代码(SQL Server 2012 产生的):
ALTER TABLE [dbo].[PriceListRows] WITH NOCHECK ADD CONSTRAINT [CK_PriceListRows_RowNo_Is_Not_Unqiue_In_PriceList] CHECK (([dbo].[tfn_CheckPriceListRows_UniqueNo]([No],[Id],[PriceListChapterId],[ProjectId])=(1)))
GO
ALTER TABLE [dbo].[PriceListRows] CHECK CONSTRAINT [CK_PriceListRows_RowNo_Is_Not_Unqiue_In_PriceList]
GO
** 编辑 3 **
执行计划在这里:https://www.dropbox.com/s/as2r92xr14cfq5i/execution%20plans.zip?dl=0
** 编辑 4 **
RowInfsView 定义为:
SELECT dbo.PriceListRows.Id, dbo.PriceListRows.No, dbo.PriceListRows.Title, dbo.PriceListRows.UnitCode, dbo.PriceListRows.UnitPrice, dbo.PriceListRows.RowStateCode, dbo.PriceListRows.PriceListChapterId,
dbo.PriceListChapters.Title AS PriceListChapterTitle, dbo.PriceListChapters.No AS PriceListChapterNo, dbo.PriceListChapters.PriceListCategoryId, dbo.PriceListCategories.No AS PriceListCategoryNo,
dbo.PriceListCategories.Title AS PriceListCategoryTitle, dbo.PriceListCategories.PriceListClassId, dbo.PriceListClasses.No AS PriceListClassNo, dbo.PriceListClasses.Title AS PriceListClassTitle,
dbo.PriceListClasses.PriceListId, dbo.PriceLists.Title AS PriceListTitle, dbo.PriceLists.Year, dbo.PriceListRows.ProjectId, dbo.PriceListRows.IsTemplate
FROM dbo.PriceListRows INNER JOIN
dbo.PriceListChapters ON dbo.PriceListRows.PriceListChapterId = dbo.PriceListChapters.Id INNER JOIN
dbo.PriceListCategories ON dbo.PriceListChapters.PriceListCategoryId = dbo.PriceListCategories.Id INNER JOIN
dbo.PriceListClasses ON dbo.PriceListCategories.PriceListClassId = dbo.PriceListClasses.Id INNER JOIN
dbo.PriceLists ON dbo.PriceListClasses.PriceListId = dbo.PriceLists.Id
【问题讨论】:
-
您要插入相同的 2 个值(100943 和 2)250 次?听起来你应该已经在第二行得到异常
-
@jamez 完全正确!这是为了测试。我应该得到错误,但我不知道为什么我不明白。 (实际上我得到了 250 条记录插入,但不是 251 条!)
-
是的,很奇怪。我编辑了帖子。
-
@MahmoudMoravej 。 . . Martin Smith 在回答类似问题 (sqlblog.com/blogs/alexander_kuznetsov/archive/2009/06/25/…) 时引用了此博客。我怀疑某种外键约束或唯一约束可能更适合您想要做的事情。
-
您选择了前 1 名而没有排序依据,因此它可以从 ChapterInfoView 中选择任意随机行与 RowInfsView 进行比较,所以在不了解您的数据的情况下,我会说这是您问题的根源。跨度>
标签: sql-server tsql user-defined-functions check-constraints