检查约束不适用于超过 250 条记录的批量插入

2024-02-09

我的查询:

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 to SELECT TOP 251(是的!只需将 250 更改为 251!)查询成功运行,没有任何检查约束异常!

为什么会有这种奇怪的行为?

NOTES :

  1. 我的检查约束是一个检查某种唯一性的函数。它查询 4 ​​个表。

  2. 我检查了 SQL Server 2012 SP2 和 SQL Server 2014 SP1

** EDIT 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

** EDIT 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

** EDIT 3 **

执行计划在这里:https://www.dropbox.com/s/as2r92xr14cfq5i/execution%20plans.zip?dl=0 https://www.dropbox.com/s/as2r92xr14cfq5i/execution%20plans.zip?dl=0

** EDIT 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

解释是你的执行计划正在使用"wide" https://blogs.msdn.microsoft.com/bartd/2006/07/27/wide-vs-narrow-plans/(逐个索引)更新计划。

这些行将在计划的第 1 步插入到聚集索引中。并且在步骤 2 中对每一行验证检查约束。

在将所有行插入聚集索引之前,不会将任何行插入非聚集索引。

这是因为有两个阻塞运算符 https://blogs.msdn.microsoft.com/craigfr/2006/06/19/properties-of-iterators/聚集索引插入/约束检查和非聚集索引插入之间。急切的线轴(步骤 3)和排序(步骤 4)。这两种方法在消耗完所有输入行之前不会产生输出行。

标量 UDF 的计划使用非聚集索引来尝试查找匹配的行。

在检查约束运行时,尚未将任何行插入到非聚集索引中,因此该检查为空。

当您插入较少的行时,您会得到一个“狭窄的”(逐行)更新计划并避免该问题。

我的建议是避免在检查约束中进行这种验证。很难确定代码在所有情况下(例如不同的执行计划和隔离级别)都能正确工作,而且它们块并行性 https://www.brentozar.com/archive/2016/04/another-hidden-parallelism-killer-scalar-udfs-check-constraints/在针对表的查询中。尝试以声明方式执行此操作(需要连接到其他表的唯一约束通常可以通过索引视图来实现)。


一个简化的重现是

CREATE FUNCTION dbo.F(@Z INT)
RETURNS BIT
AS
  BEGIN
      RETURN CASE WHEN EXISTS (SELECT * FROM dbo.T1 WHERE  Z = @Z) THEN 0 ELSE 1 END
  END

GO

CREATE TABLE dbo.T1
  (
     ID INT IDENTITY PRIMARY KEY,
     X  INT,
     Y  CHAR(8000) DEFAULT '',
     Z  INT,
     CHECK (dbo.F(Z) = 1),
     CONSTRAINT IX_X UNIQUE (X, ID),
     CONSTRAINT IX_Z UNIQUE (Z, ID)
  )

--Fails with check constraint error
INSERT INTO dbo.T1 (Z)
SELECT TOP (10) 1 FROM master..spt_values;

/*I get a wide update plan for TOP (2000) but this may not be reliable 
  across instances so using trace flag 8790 to get a wide plan. */
INSERT INTO dbo.T1 (Z)
SELECT TOP (10) 2 FROM master..spt_values
OPTION (QUERYTRACEON 8790);

GO

/*Confirm only the second insert succceed (Z=2)*/
SELECT * FROM dbo.T1;

DROP TABLE dbo.T1;    
DROP FUNCTION dbo.F; 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

检查约束不适用于超过 250 条记录的批量插入 的相关文章

  • SQL Server 使用通配符加入并在第一个匹配处停止

    IF OBJECT ID tempdb TABLE1 IS NOT NULL DROP TABLE TABLE1 IF OBJECT ID tempdb TABLE2 IS NOT NULL DROP TABLE TABLE2 CREATE
  • SQL Server Express 到 .mdf 文件的连接

    两部分问题 我使用 VS 2015 Update 3 创建了一个 ASP NET MVC 5 应用程序 我在本地计算机上完成了该项目 突然 我无法再通过 SQL Server 对象资源管理器连接到 mdf数据库文件并出现以下错误 无法打开数
  • 将多行合并为一行并根据行数附加列

    我正在尝试将同一个表的多行合并为一个 我有一个像这样的示例表 Col1 Col2 Col3 Col4 Col5 Col6 1 BH1 CB 12 CC CC Conveyor Mal 1 BH1 CB 104 ZC ZC Full Emp
  • SQL Server 中的派生表

    我有这两个疑问 我不知道如何将它们组合在一起来制作派生表 我假设使用第二个查询作为主查询 并在主查询的 FROM 子句中使用第一个查询 SELECT EmailAddress Orders OrderID SUM ItemPrice Qua
  • SqlException超时未达到

    我们的服务器有时会抛出这个众所周知的异常 超时已过 操作完成之前超时时间已过 或者服务器未响应 当服务器处理大请求时 这种情况会在压力下发生 我做了一些研究 发现我可以改变连接字符串连接超时设置和 或SqlCommand 超时数据读取器属性
  • SQL Server递归查询显示父级路径

    我正在使用 SQL Server 语句并有一张表 例如 item value parentItem 1 2test 2 2 3test 3 3 4test 4 5 1test 1 6 3test 3 7 2test 2 我想使用 SQL S
  • 如何对 SQL Server Express 进行实时更改

    我一直在使用 VS studio 开发一个 ASP NET Web 应用程序 我正在使用 SQL Server Express 在开发过程中 我一直在我的服务器上测试我的网络应用程序 每次我需要更新数据库时 我都会简单地删除旧数据库 位于我
  • 在 SSIS 中使用合并任务的指南

    我有一个包含三个字段的表 其中一个是身份字段 我需要从具有其他两个字段的源中添加一些新记录 我正在使用SSIS 我认为我应该使用合并工具 因为其中一个源不在本地数据库中 但是 我对合并工具和正确的过程感到困惑 我有一个源 一个 Oracle
  • 在 Navicat Premium 中连接到 LocalDB 服务器

    Recently I installed LocalDb Serer on my laptop I am trying to establish a connection between Navicat and LocalDB server
  • 仅基于月份和年份的 SQL Server 日期比较

    我无法确定仅根据月份和年份比较 SQL 中的日期的最佳方法 我们根据日期进行计算 由于计费是按月进行的 因此该月的日期会造成更多障碍 例如 DECLARE date1 DATETIME CAST 6 15 2014 AS DATETIME
  • SSIS 将字符转换为布尔值/位

    我有一个SSIS包来加载数据 您可能还记得 当我尝试将数据文件中的标志作为位标志加载到 SQL Server 中时 这些标志作为 Y N char 1 存在 我将数据文件中的列指定为String DT STR 我有一个数据转换任务 根据以下
  • 临时表上没有外键限制? SQL Server 2008

    我知道临时表只会在 SQL Server 会话打开时存在 但为什么不能对它们进行外键限制呢 想象一下这样的场景 您创建从临时表到具体表的键的外键关系 外键关系的限制之一是您无法从临时表所依赖的键表中删除行 现在 通常当您创建外键关系时 您知
  • 如何获取 dm_exec_sql_text 的参数值

    我正在运行以下语句来查看 sql server 中正在执行哪些查询 select from sys dm exec requests r cross apply sys dm exec sql text r sql handle where
  • sql中的拓扑排序

    我正在解决表中某些对象之间的依赖关系 我必须对对象做一些事情来排序它们的依赖性 例如 第一个对象不依赖于任何对象 第二个和第三个取决于第一个 依此类推 我必须使用拓扑排序 http en wikipedia org wiki Topolog
  • SQL Server 全文的自定义断字器

    有谁知道如何为 SQL Server 2005 创建自定义分词系统 我更喜欢用 C 编写它 我需要能够搜索 c f 等术语 但 字符是英语 英国 分词器组件中的分词器 不能以任何其他方式更改 我发现以下文章提供了不完整的示例 缺少 IWor
  • NOLOCK 和 UNCOMMITTED 之间有什么区别

    我使用 SQL Server 2012 我写了两个查询 但是它们之间有什么不同NOLOCK and UnCommitted SELECT lastname firstname FROM HR Employees with READUNCOM
  • 在为存储过程设置参数时,可以在 new SqlParameter 的构造函数中设置 TypeName 吗?

    我使用以下代码来设置调用存储过程的参数 List
  • SQL Server:删除具有外键约束的行:事务可以覆盖约束吗?

    我有一些添加了外键约束的表 它们与代码生成一起使用 以在生成的存储过程中设置特定的联接 是否可以通过在事务中调用多个删除来覆盖这些约束 特别是 C 中的 TransactionScope 或者绝对需要级联删除吗 不要使用级联删除 这样可能会
  • 如何使用jdbc驱动编写事务?

    我想使用 jdbc 编写一个事务java 我尝试过这个简单的交易 BEGIN TRANSACTION NL GO NL UPDATE table SET col test where id 1010 NL GO NL COMMIT 我尝试过
  • 如何在多行上使用 OPENJSON

    我有一个临时表 其中包含多行 每行都有一个名为Categories 其中包含一个非常简单的 json 数组ids对于不同表中的类别 临时表的一些示例行 Id Name Categories 539f7e28 143e 41bb 8814 a

随机推荐

  • CKEDITOR,在文本编辑器 onLoad 上自动聚焦

    有人知道如何在页面加载时自动聚焦于 CKEDITOR 文本区域吗 目前 用户必须先单击文本区域才能开始输入 像 Google 一样 我希望加载页面 并且用户可以立即开始输入 而无需单击文本区域 这是启动 CKEDITOR 的当前代码
  • webRTC - 视频导致互联网上的通话中断

    更新1 我尝试像这样改变视频约束 var mediaConstraints audio true We want an audio track video width min 160 ideal 320 max 640 height min
  • 浏览器使用哪种等宽字体?

    对于 CSS 如果您指定font family monospace 我的理解是浏览器选择其默认 首选等宽字体 如果这是正确的 您如何确定您的浏览器正在使用哪种等宽字体 可以使用 5 个通用系列 serif sans serif cursiv
  • 在 Notepad++ 中显示不匹配的 html 标签

    有没有办法在 Notepad 中突出显示不匹配的 HTML 标签 例如 如果我有以下 HTML 我想要标签以某种方式突出显
  • 由于一个或多个外键属性不可为空,因此无法更改该关系

    使用 EF 更新期间出现以下错误 操作失败 无法更改关系 因为一个或多个外键属性不可为空 当关系发生更改时 相关的外键属性将设置为空值 如果外键不支持空值 则必须定义新关系 必须为外键属性分配另一个非空值 或者必须删除不相关的对象 有没有g
  • Codeigniter 论坛集成

    我想将一个简单的论坛与 Codeigniter 应用程序集成 想知道是否有人有任何建议 干杯 Laurence 我会看一下普通论坛 有很多插件 开源 而且很容易集成 即 Codeigniter http vanillaforums org
  • 以编程方式设置 UIView 的自动调整大小掩码?

    我必须以编程方式设置 autoresizingMaskUIView 我不知道如何实现这个 要实现屏幕截图中的效果 您需要执行与 DrummerB 建议相反的操作 你想要一个固定的上边距 这样你就可以让其他每一面都变得灵活 如下所示 目标C
  • 指定 Python argparse 输入参数的日期格式

    我有一个需要一些命令行输入的 Python 脚本 我正在使用argparse用于解析它们 我发现文档有点混乱 找不到检查输入参数格式的方法 我通过以下示例脚本解释了检查格式的含义 parser add argument s startdat
  • 如何在 Scala 代码中读取压缩的 xml 文件?

    如何直接从 Scala 程序中的压缩文件访问 XML 数据文件 有没有直接的方法可以以编程方式解压缩并读取 Scala 代码中的内容 以下是 2 8 1 中执行此操作的几种方法 cat gt root xml lt lt EOF
  • 如何在具有 API 7 的 Android 应用程序中使用 NumberPicker?

    我的应用程序的最小 sdk 是 7 但我可以使用 sdk 版本 11 中的 DialogFragment 因为它位于我的 lib 目录中的支持库中 我想做这样的例子 http developer android com guide topi
  • 如何防止 IE 中的 javascript: href 链接触发 window.onbeforeunload ?

    我正在为我的表单构建一个故障安全机制 它将警告用户 如果他们离开页面 他们的表单数据将会丢失 类似于 gmail 的做法 window onbeforeunload function if formIsDirty return You ha
  • 从直方图曲线中选择最佳值范围

    设想 我正在尝试跟踪两个不同颜色的物体 一开始 系统会提示用户将第一个彩色对象 例如 可能是红色 放在相机前面的特定位置 在屏幕上用矩形标记 并按任意键 然后我的程序将获取帧的该部分 ROI 并分析其中的颜色 找到要跟踪的颜色 对于第二个对
  • Edge chromium 不会显示基本身份验证弹出窗口?

    我有一个 Apache 服务器 v2 4 43 为我的网站提供服务 并且我使用一个简单的 htpasswd 我使用指令 AuthUserFile 在 htaccess 中调用它来进行身份验证 现在 该解决方案适用于所有浏览器 将显示一个弹出
  • 应用程序内的 Dropbox 身份验证

    有什么方法可以在 iPhone 中的 Dropbox 应用程序中对用户进行身份验证吗 I using Dropbox IOS https www dropbox com developers start authentication ios
  • 如果一个同步方法调用另一个非同步方法,该非同步方法是否有锁

    在Java中 如果一个同步方法包含对非同步方法的调用 那么另一个方法是否仍然可以同时访问该非同步方法 基本上我要问的是同步方法中的所有内容都有锁 包括对其他同步方法的调用 如果一个同步方法调用另一个非同步方法 该非同步方法是否有锁 答案取决
  • 仅在第一次使用 Rspec 调用时存根方法

    如何仅在第一次调用时存根方法 而在第二次调用中它应该按预期运行 我有以下方法 def method do stuff rescue gt MyException sleep rand retry end 我想要的第一个电话do stuff募
  • const 多维数组初始化

    为什么下面的方法有效 class A public int i 1 2 3 1 2 3 1 2 3 static void Main string args 而以下则不然 class A public const int i 1 2 3 1
  • 我可以使用 OkHttp 将本地 IP 地址绑定到我的 SSLSocketFactory 吗?

    我正在努力让 Android 上的 OkHttpClient 使用自定义证书发出 HTTPS 请求 同时绑定到特定网络接口的本地地址 我目前的尝试使用以下内容OkHttpClient val client OkHttpClient Buil
  • 将 pnglib 中的数据显示为 ximage

    我需要导入 PNG 并将其显示在 Motif 应用程序的屏幕上 由于我自己最清楚的原因 我不想使用超出需要的库 并且我想只使用 Motif 和 pnglib 我已经为此奋斗了几天 我想放下我的骄傲并寻求一些帮助 此屏幕截图显示了问题 htt
  • 检查约束不适用于超过 250 条记录的批量插入

    我的查询 INSERT into PriceListRows PriceListChapterId No SELECT TOP 250 100943 N 2 FROM AnyTable 该查询工作正常 并且根据需要引发以下异常 INSERT