使用直接查询和存储过程对同一个表进行多次插入请求会导致冲突吗?

发布于 2024-11-09 06:44:46 字数 1416 浏览 0 评论 0原文

Multiply用户可以调用存储过程(SP),这将对SQL Server中的mytable进行一些更改。此 SP 应将一些行插入到通过 parentid 列引用自身的 mytable 中。

TABLE mytable(
   id int identity(1,1) primary key,
   name varchar(20) not null,
   parentId int not null foreign key references mytable(id)
)  

为了将行插入到此类表中,根据其他帖子,我有两种方法:

  1. 通过ALTER TABLE mytable alter column Parentid int null;允许parentid列为空,插入该行,更新 parentid 并禁用 null 为 parentid
  2. 通过 set Identity_insert maytable on 允许 IDENTITY,插入虚拟行使用 id=-1parentid=-1,插入引用 -1 的正确行,更新 parentid 到 SCOPE_IDENTITY() 并最终将 IDENTITY 设置为关闭

案例:

假设我采用第二种方式。 SP 成功将identity_insert mytable 设置为 但是 尚未完成其余SP 的执行。此时,还有其他 INSERT 请求(不通过 SP)发送到 mytable 表,例如 INSERT INTO mytable(name,parentid) VALUES('theateist', -1)。没有指定 id,因为他们假设 IDENTITY 已关闭,因此 id 是自动递增的。

问题:

插入时会不会出现错误,因为IDENTITY在这段时间内是ON的,不再自动递增,因此需要id规范?如果是的话,使用第一种方式会更好,不是吗?

谢谢

Multiply users can call store procedure(SP), that will make some changes to mytable in SQL Server. This SP should insert some rows to mytable that has reference to itself through parentid column.

TABLE mytable(
   id int identity(1,1) primary key,
   name varchar(20) not null,
   parentId int not null foreign key references mytable(id)
)  

in order to insert row to such table, accordingly to other posts, I have 2 ways:

  1. Allow null to parentid column by ALTER TABLE mytable alter column parentid int null;, insert the row, update parentid and than disable null to parentid
  2. Allow IDENTITY by set identity_insert maytable on, insert dummy row with id=-1 and parentid=-1, insert the correct row with reference to -1, update the parentid to SCOPE_IDENTITY() and in the end set IDENTITY to off

The case:

Assume I take the 2nd way. SP managed to set identity_insert mytable on BUT didn't yet finished the execution of the rest SP. At this time, there are other INSERT requests(NOT through SP) to the mytable table like INSERT INTO mytable(name,parentid) VALUES('theateist', -1). No id is specified because they assumed that IDENTITY is off and therefore id is auto-incremental.

The Question:

Will this cause errors while inserting because IDENTITY, in this period of time, is ON and not auto-incremental any more and therefore it will require id specification? If yes, it will be better to use the 1st way, isn't it?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

子栖 2024-11-16 06:44:46

identity_insert 是每个连接的设置 - 您不会影响针对此表运行的其他连接/语句。

如果可以避免的话,我绝对不建议采用第一种方式,因为它可能会影响表的其他用户 - 例如,其他一些连接可能会执行损坏的插入(parentid=null),而列定义允许这样做,然后您的存储过程将中断。此外,设置列not null 会强制进行全表扫描,因此随着表的增长,这将无法正常工作。

如果您确实坚持使用方法 2,那么您仍然会遇到两个连接同时运行此存储过程时会发生什么的问题 - 它们都希望在不同时间插入 -1 行,并将其也删除。你们会有冲突。

我猜你遇到的问题是插入树的“根”,因为它们没有父级,所以你试图让它们自我引用。相反,我可能会让根永久具有空的parentid。如果还有其他一些键列,则可以在筛选索引或索引视图中使用这些键列,以确保每个键仅存在一个根。


想象一下,我们正在构建某种形式的家谱,并忽略了此类野兽的大部分现实(例如大多数要求孩子有两个父母的家庭):

CREATE TABLE People (
    PersonID int IDENTITY(1,1) not null,
    Surname varchar(30) not null,
    Forename varchar(30) not null,
    ParentID int null,
    constraint PK_People PRIMARY KEY (PersonID),
    constraint FK_People_Parents FOREIGN KEY (ParentID) references People (PersonID)
)

CREATE UNIQUE INDEX IX_SoleFamilyRoot ON People (Surname) WHERE (ParentID is null)

这确保了在每个家庭(按姓氏标识)内,准确地一个人的 ParentID 为空。希望您可以修改此示例以适合您的模型。

在 SQL Server 2005 及更早版本上,您必须改用索引视图。

identity_insert is a per-connection setting - you won't affect other connections/statements running against this table.

I definitely wouldn't suggest going the first way, if it could be avoided, since it could impact other users of the table - e.g. some other connection could do a broken insert (parentid=null) while the column definition allows it, and then your stored proc will break. Also, setting a column not null forces a full table scan to occur, so this won't work well as the table grows.

If you did stick with method 2, you've still got an issue with what happens if two connections run this stored proc simultaneously - they'll both want to insert the -1 row, at different times, and delete it also. You'll have conflicts.

I'm guessing the problem you're having is inserting the "roots" of the tree(s), since they have no parent, and so you're attempting to have them self referencing. I'd instead probably make the roots have a null parentid permanently. If there's some other key column(s), these could be used in a filtered index or indexed view to ensure that only one root exists for each key.


Imagine that we're building some form of family trees, and ignoring most of the realities of such beasts (such as most families requiring children to have two parents):

CREATE TABLE People (
    PersonID int IDENTITY(1,1) not null,
    Surname varchar(30) not null,
    Forename varchar(30) not null,
    ParentID int null,
    constraint PK_People PRIMARY KEY (PersonID),
    constraint FK_People_Parents FOREIGN KEY (ParentID) references People (PersonID)
)

CREATE UNIQUE INDEX IX_SoleFamilyRoot ON People (Surname) WHERE (ParentID is null)

This ensures that, within each family (as identified by the surname), exactly one person has a null ParentID. Hopefully, you can modify this example to fit your model.

On SQL Server 2005 and earlier, you have to use an indexed view instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文