如何翻转 T-SQL 中的位域?

Posted

技术标签:

【中文标题】如何翻转 T-SQL 中的位域?【英文标题】:How to flip bit fields in T-SQL? 【发布时间】:2009-09-09 03:00:43 【问题描述】:

我正在尝试使用更新查询翻转 SQL Server 中的位字段,也就是说,我想将所有 0 变为 1,反之亦然。什么是最优雅的解决方案?

T-SQL 中似乎没有按位 NOT 运算符(除非我遗漏了一些明显的东西),而且我找不到任何其他执行更新的方法。

【问题讨论】:

【参考方案1】:

您不需要按位进行 - 只需将其与 1 / true 异或即可。

检查:

select idColumn, bitFieldY, bitFieldY ^ 1 as Toggled
from tableX

更新:

update tableX
set bitFieldY = bitFieldY ^ 1
where ...

MSDN T-SQL Exclusive-OR (^)

【讨论】:

太棒了!谢谢你 - 它就像一个魅力。我显然需要更多地了解如何使用二元运算符 另一篇:blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/… 请记住,bitFieldY ^ 1 将返回 int,因此如果您需要它再次成为 bitCASTCONVERT 将返回到 bit【参考方案2】:

为什么不简单的bitfield = 1 - bitfield

【讨论】:

一种巧妙而优雅的方法,特别是对于一次性查询,可读性并不重要。 @Billious 和 GBN 你们都是对的,但我想 Austin 的回复足以理解目标的明确含义。用 1-x 翻转一点会使新手感到困惑,因此不是实现它的正确方法。我也同意做某事的方法不止一种,但如果有推荐的方法,我们应该采用它,这可能比不推荐的方法更快。 对于可以为空的bitfield,一种方法可能是bitfield = 1 - ISNULL(bitfield,0)。请参阅文档中的ISNULL。 @UweKeim 就个人而言,我不使用 NULLable 位。从来没有真正需要 3 个状态来处理比特 谢谢,@gbn。我有时在有一个遗留表时会这样做,我稍后会在其中添加一个新的位域列。 (如果有更多的知识,这可能会更优雅地解决)。【参考方案3】:

另一种方法是

DECLARE @thebit bit = 1, @theflipbit bit

SET @theflipbit = ~ @thebit

SELECT @theflipbit

其中“~”表示“NOT”运算符。它很干净,您可以阅读很好的代码。 “否定位”更加简洁,它完全符合“NOT”运算符的设计目的。

【讨论】:

同样的想法,但将 NULLS 变为 true:UPDATE TABLE_NAME SET BIT_FIELD= IIF(BIT_FIELD IS NULL,1,~ BIT_FIELD)【参考方案4】:

我很确定大多数 SQL 风格都有按位 NOT,所以我检查了一下,确实有 appear to be one in TSQL。

从文档中,它是字符 ~

【讨论】:

SELECT ~MyBitField from MyTable 换句话说,更新 MyTable set MyBitField = ~MyBitField【参考方案5】:
UPDATE tblTest SET MyBitField = CASE WHEN MyBitField = 1 THEN 0 ELSE 1 END

这很乏味,但每个人都会明白它在做什么。

编辑:

您可能还需要按照 cmets 中的建议考虑空值。当然取决于你的需求。

UPDATE tblTest SET 
   MyBitField = CASE 
      WHEN MyBitField = 1 THEN 0 
      WHEN MyBitField = 0 THEN 1
      ELSE NULL -- or 1 or 0 depending on requirements
   END

【讨论】:

这会将 MyBitField 设置为 1,当它以 NULL 开始时。不完全是翻转位。 我认为这是不言而喻的......但我会添加有关处理空值的信息以防万一。 我倾向于同意其他一些人的观点并选择 ~ 或 "^ 1 "。特别是如果这是一次性的事情(看起来更干净)。但是,如果这会持续存在并且可维护性存在问题,那么这个解决方案肯定是最直接的。 在我的例子中,这是一个一次性查询,所以可维护性不是问题,但是,是的,这同样可以很好地工作。我实际上已经编写了一个类似的查询,但无法让 CASE 语句正常工作。我现在意识到这是一个简单的语法错误。哦! 我也喜欢这个。我有时会发现,如果我在代码中遇到一个我不理解的符号,那么很难弄清楚编码器的意图。但这很明显。【参考方案6】:

一个简单的按位非运算符 (~) 在 SQL Server 2014 - 12.0.2269.0 中为我工作

在 T-SQL 中的更新子句中 -

        Update TableName
        SET    [bitColumnName] = ~[bitColumnName],
               ....
        WHERE  ....

希望对你有帮助

参考 - https://docs.microsoft.com/en-us/sql/t-sql/language-elements/bitwise-not-transact-sql

【讨论】:

【参考方案7】:

你试过了吗?

UPDATE mytable SET somecolumn = 
  CASE WHEN somecolumn = 0 THEN 1 
       WHEN somecolumn IS NULL THEN NULL
       WHEN somecolumn = 1 THEN 0
  END

【讨论】:

【参考方案8】:

查询 (vb)

x = "select x from table"

更新(vb)

"update table set x=" Not(x*(1))

【讨论】:

即使在 vb 中这也不起作用,问题是针对 t-sql

以上是关于如何翻转 T-SQL 中的位域?的主要内容,如果未能解决你的问题,请参考以下文章

澄清 C 中的位域排序语义

如何模拟Delphi records中的位域

C/C++ 位域知识小结

C 和 C++ 中的位域:它们在哪里使用?

共享库中的位域可移植性

记录C中的位域