【问题标题】:Update all /some / no columns depending on other column values根据其他列值更新所有/一些/无列
【发布时间】:2013-03-31 13:56:03
【问题描述】:

我想知道是否可以在 SQL 中执行以下操作(我使用的是 SQL Server 2008+,因此特定于供应商的东西暂时也可能有用):

我有下表:

contact (contactid, fullname, fullname_timestamp, age, age_timestamp)

我只想更新那些“*_timestamp”列小于给定值的列。例如:

UPDATE contact
SET    fullname = 'john doe' IF fullname_timestamp < 12345,
       age = 30 IF age_timestamp < 12345
WHERE  contactid = 'abcde'

将这些条件放在 WHERE 子句中会产生“全有或全无”的情况(我认为?),而鉴于这些“时间戳”约束,我想“部分更新”记录。

这可能吗/我做错了吗?欢迎提出建议。 提前致谢。

编辑:@AaronBertrand 提出了一些要点,我认为它们值得一提,作为问题的附加信息。我还要承认,我仍然在脑海中想出一个解决方案,而且我的想法可能存在差距。

我正在复制外部产品中包含的数据。该产品具有明确定义的 CRUD 事件管道。由于性能原因,我正在异步管理这些事件。 这些事件可能会乱序排队以供以后处理。 我在上述产品的非异步管道阶段之一中使用 DateTime.UtcNow.Ticks 时间戳 - 以便记录正确加时间戳 - 我有办法判断我要更新的数据是否是最新的-日期或陈旧。

-- sync pipeline --

record update 1 - timestamp 1
record update 2 - timestamp 2

-- async queue (can be out-of-order) --
record update 2 - timestamp 2 -> sent to db
record update 1 - timestamp 1 -> sent to db

-- replica db  --
record update 2 goes through, the timestamp is ok
record update 1 does nothing, timestamp shows data is out-of-date

是的,更新可以同时发生在相同的记录上。用户可以同时修改相同或不同的字段。 希望这是有道理的。感谢大家的宝贵意见。

【问题讨论】:

  • 。 .如果更改值,是否也要更改时间戳?
  • 这实际上是一个好问题,@GordonLinoff。是的,我愿意。我认为时间戳在 SQL 中具有特定含义,现在我正在考虑 DateTime.UtcNow.Ticks。
  • 。 .您应该按照 Robertco 的建议调查键/值对。对于您的数据来说,这可能是一种更好的结构。
  • 你认为只更新一行有好处吗? (In my tests, just updating the whole row always won, performance-wise.) 您是否依赖时间戳来验证值是否实际发生了变化?为什么不比较值?这闻起来很像过早的优化。如果您要更新行中的 any 值,也可以更新整行。我认为您的结构对于维护每个列值的排序历史并不理想。无论如何,您将如何处理这些信息?
  • 另外,如果您使用DateTime.UtcNow 作为比较,根据定义,表中的所有值是否都已小于更新时的值?

标签: sql sql-server tsql sql-update


【解决方案1】:

您可以在此使用CASE 来测试某个列的特定条件,

UPDATE contact
SET    fullname = CASE WHEN fullname_timestamp < 12345 THEN 'john doe' ELSE fullname END,
       age = CASE WHEN age_timestamp < 12345 THEN 30 ELSE age END
WHERE  contactid = 'abcde'

【讨论】:

  • 太棒了!我想这正是我正在寻找的,谢谢。 (还有 9 分钟...)
  • 正确答案,但如果您计划为每一列添加时间戳,您可能需要考虑键/值对。
  • @RobertCo 你能扩展一下吗?我很想学习不同的做法。
  • 显然,我不应该假装知道你想做什么。但无论如何我都会。如果你想创建一个更改的“日志”,你可以比非常列上的时间戳做得更好。删除主表上的时间戳并创建一个包含 ff 列的单独表:contact_id、attr_id、timestamp,其中 attr id 是分配给您计划监控的每一列的 id,然后继续插入。
  • 我想我明白你的意思,如果我需要日志工具,我肯定会考虑这个。然而,在这种特殊情况下,我的目标是防止来自无序来源的更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
相关资源
最近更新 更多