多个 SQL UPDATE 语句还是单个包含 CASE 的语句?
我构建了一个触发器,试图保持优先级顺序并且不允许重复的优先级值。有一些事情需要考虑。
- 用户可以自由设置优先级。
- 没有什么可以阻止他们选择与另一个项目相同的优先级。
当输入的值等于另一个值时,新确定优先级的项目应优先考虑优先级,而另一个值应递增。
创建触发器 dbo.trg_Priority ON dbo.故事 插入、更新、删除后 作为 开始 设置不计数; -- 在此插入触发器语句 声明@StoryId INT 声明@OldLocation INT 声明@NewLocation INT 从插入中选择 @NewLocation = 优先级,@StoryId = StoryId 选择@OldLocation = 优先删除 IF @NewLocation = @OldLocation 返回; IF @NewLocation 为 NULL 开始 更新故事集 优先级 = 优先级 - 1 其中优先级> @旧位置 结尾 如果@NewLocation> @旧位置 开始 更新故事集 优先级 = 优先级 + 1 WHERE 优先级 >= @NewLocation 和 StoryId <> @StoryId 结尾 如果@NewLocation < @旧位置 开始 更新故事集 优先级 = 优先级 + 1 WHERE 优先级 >= @NewLocation 且优先级< @旧位置 和 StoryId <> @StoryId 结尾 结尾 去
我还没有对这个触发器进行过多次测试,所以如果有什么值得关注的地方,请随意说出来。我最终想知道的是我是否应该尝试将其转换为带有 case 语句的单个更新。 (如果这甚至可能的话。)
如果将其设为单个 UPDATE 语句会更高效,我真的可以用手来解决它!
I've built a trigger where I am trying to keep priorities in order and not allow duplicate priority values. There are some things to consider.
- The user can free form the priority in.
- There is nothing blocking them from picking the same priority as another item.
When a value is entered equal to another value the newly prioritized item should take precedence in the priority and the other should be incremented.
CREATE TRIGGER dbo.trg_Priority ON dbo.Stories AFTER INSERT,UPDATE,DELETE AS BEGIN SET NOCOUNT ON; -- Insert statements for trigger here DECLARE @StoryId INT DECLARE @OldLocation INT DECLARE @NewLocation INT SELECT @NewLocation = Priority, @StoryId = StoryId FROM INSERTED SELECT @OldLocation = Priority FROM DELETED IF @NewLocation = @OldLocation RETURN; IF @NewLocation IS NULL BEGIN UPDATE Stories SET Priority = Priority - 1 WHERE Priority > @OldLocation END IF @NewLocation > @OldLocation BEGIN UPDATE Stories SET Priority = Priority + 1 WHERE Priority >= @NewLocation AND StoryId <> @StoryId END IF @NewLocation < @OldLocation BEGIN UPDATE Stories SET Priority = Priority + 1 WHERE Priority >= @NewLocation AND Priority < @OldLocation AND StoryId <> @StoryId END END GO
I haven't tested this trigger a whole lot so if there's areas of concern feel free to speak up. What I ultimately want to know is if I should try and convert this to a single update with a case statement. (If that's even possible.)
If it would be more performant to make this a single UPDATE
statement I could really use a hand figuring it out!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要重写触发器。它假设一次只会插入/更新或删除一条记录。您不能用这种假设编写触发器,触发器对批量数据进行操作,而不是逐行操作。您需要加入才能在更新中插入和删除。所以是的,我会尝试用案例陈述来编写更新。
为什么这是一个已删除的触发器?如果删除,则不会有记录可更新。
You need to rewrite the trigger. It assumes only one records will ever be inserted/updated or delted at atime. You cannot write a trigger with that assumption, triggers operate on batches of data not row-byrow. You need to join to inserted and deleted in your updates. So yes, I would try to write the update with a case statement.
And why is this a deleted trigger? There won;t be arecord to update if it was deleted.
确保在 @@ROWCOUNT > 时回滚并引发错误(严重性 16)。 1. 当前编写的触发器会导致用户尝试一次插入、更新或删除多行,从而导致大量数据损坏。
也就是说,IronGoofy 是对的:无论情况如何,您只会接触桌子一次。因此,将其分解为多个语句使代码更易于阅读/更易于维护。
如果您允许一次更新多行,则需要更改此设置。逻辑可能令人畏惧!
Make sure you rollback and raise an error (severity 16) if @@ROWCOUNT > 1. Your trigger as currently written would cause a great deal of data corruption of the user attempted to insert, update or delete multiple rows at once.
That said, IronGoofy is right: you will only be touching the table once, regardless if the condition. So, breaking it out into multiple statements makes the code easier to read/more maintainable.
If you were to allow multiple rows to be updated at once, you would need to change this. The logic may be daunting!
这个怎么样:
How about this:
不应该有任何(明显的)性能差异,在任何情况下您都会向数据库发出单个更新语句。
There shouldn't be any (noticeable) performance difference, in any case you will be issuing a single update statement to the database.
我决定放弃这个想法,并让 UI 来更新优先级。我已停止允许用户输入。
我不确定这些答案中哪个是正确的,因此我将其标记为正确,并让社区通过反复试验找出答案。 :)
I decided to ditch this idea, and I leave it up to the UI to update the priority. I've stopped allowing user input.
I'm not sure which of these answers are correct, so I'm going to mark this as correct and let the community figure it out with trial and error. :)