更新与唯一索引冲突的多行

发布于 2024-08-27 15:09:34 字数 297 浏览 12 评论 0原文

我正在使用 Microsoft SQL Server,并且有一个主从场景,我需要存储详细信息的顺序。因此,在详细信息表中,我有 ID、MasterID、Position 和其他一些列。 MasterID和Position也有一个唯一的索引。它工作正常,除了一种情况:当我有一些现有的详细信息并且我更改了它们的顺序时。例如,当我用位置 2 的详细信息更改位置 3 的详细信息时。当我保存位置 2 的详细信息(在数据库中位置等于 3)时,SQL Server 会抗议,因为索引唯一性约束。

如何合理的解决这个问题呢?

预先感谢您
卢卡斯·格拉兹

I am using Microsoft SQL Server and I have a master-detail scenario where I need to store the order of details. So in the Detail table I have ID, MasterID, Position and some other columns. There is also a unique index on MasterID and Position. It works OK except one case: when I have some existing details and I change their order. For example when I change a detail on position 3 with a detail on position 2. When I save the detail on position 2 (which in the database has Position equal to 3) SQL Server protests, because the index uniqueness constraint.

How to solve this problem in a reasonable way?

Thank you in advance
Lukasz Glaz

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

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

发布评论

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

评论(2

爱,才寂寞 2024-09-03 15:09:34

这是一个经典问题,答案很简单:如果要将第3项移动到位置2,则必须首先将2的排序列更改为临时数字(例如99)。所以它是这样的:

Move 2 to 99
Move 3 to 2
Move 99 to 3

但是,您必须小心,您的临时值永远不会在正常处理中使用,并且如果适用,您必须尊重多个线程。

更新:顺便说一句 - 处理“多个用户可能会更改订单”问题的一种方法是执行我所做的操作:为每个用户提供一个数字 ID,然后将其添加到临时号码(我的员工 ID 实际上是员工表中用于控制登录的唯一身份字段 ID。因此,例如,如果您的头寸永远不会为负,您可以使用 -1000 - UserID 作为临时值。不过请相信我一件事:您不想假设永远不会发生碰撞。如果您认为这种情况确实发生了,那么调试起来将非常困难!

更新:GUZ 指出,他的用户可能对整组订单项进行了重新排序,并将它们批量提交 - 这不仅仅是两条记录的切换。那么,您可以通过两种方式之一来解决这个问题。

首先,您可以将整个集合的现有排序字段更改为一组新的非冲突值(例如 -100 - (staffID * maxSetSize) + existingOrderVal),然后逐条记录将每个记录更改为新的值订单价值。

或者,您基本上可以将其视为数组上的冒泡排序,其中 orderVal 值相当于数组索引。要么这对您来说非常有意义(并且是显而易见的),要么您应该坚持使用解决方案 1(无论如何,这更容易)。

This is a classic problem and the answer is simple: if you want to move item 3 to position 2, you must first change the sort column of 2 to a temporary number (e.g. 99). So it goes like this:

Move 2 to 99
Move 3 to 2
Move 99 to 3

You must be careful, though, that your temporary value is never used in normal processing and that you respect multiple threads if applicable.

Update: BTW - one way to deal with the "multiple users may be changing the order" issue is to do what I do: give each user a numberical ID and then add this to the temporary number (my staff ID is actually the Unique Identity field ID from the staff table used to gate logins). So, for example, if your positions will never be negative, you might use -1000 - UserID as your temporary value. Trust me on one thing though: you do not want to just assume that you'll never have a collision. If you think that and one does occur, it'll be extremely hard to debug!

Update: GUZ points out that his users may have reordered an entire set of line items and submitted them as a batch - it isn't just a switch of two records. You can approach this in one of two ways, then.

First, you could change the existing sort fields of the entire set to a new set of non-colliding values (e.g. -100 - (staffID * maxSetSize) + existingOrderVal) and then go record-by-record and change each record to the new order value.

Or you could essentially treat it like a bubble sort on an array where the orderVal value is the equivalent of your array index. Either this makes perfect sense to you (and is obvious) or you should stick with solution 1 (which is easier in any event).

可遇━不可求 2024-09-03 15:09:34

您可以删除订单列上的唯一约束(但保留索引键),并在必要时确保代码中的唯一性。

you could just remove the unique constraint (but leave an index key) on the order column, and ensure uniqueness in your code if necessary.

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