在SQL中使用位串(而不是int)匹配位掩码

时间:2013-01-07 16:57:52

标签: sql postgresql match bitmask bitstring

我在这里找到了很棒的资源( Comparing two bitmasks in SQL to see if any of the bits match )用于在SQL数据库中进行搜索,在数据库中使用位掩码存储具有多个属性的数据。但是,在示例中,所有数据都存储为int,而where子句似乎只适用于int。

是否有一种简单的方法可以将非常相似的测试用例转换为使用完整的位串?所以不是像以下那样的例子:

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',1
    UNION SELECT 2,'Charlie',3
    UNION SELECT 3,'Susan',5
    UNION SELECT 4,'Nick',2
)
select * from test where (roles & 7) != 0 

取而代之的是:

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',B'001'
    UNION SELECT 2,'Charlie',B'011'
    UNION SELECT 3,'Susan',B'101'
    UNION SELECT 4,'Nick',B'110'
)
select * from test where (roles & B'001') != 0 

我可以来回转换,但使用实际的位串可视化更容易。对于我的简单转换(上面),我得到一个错误,操作符不适用于位串。有没有其他方法来设置它可以工作?

1 个答案:

答案 0 :(得分:7)

一种方法是在表达式的右侧使用bit string

WITH test (id, username, roles) AS (
   VALUES
     (1,'Dave',B'001')
    ,(2,'Charlie',B'011')
    ,(3,'Susan',B'101')
    ,(4,'Nick',B'110')
   )
SELECT *, (roles & B'001') AS intersection
FROM   test
WHERE  (roles & B'001') <> B'000';

或者您可以将integer 0投射到bit(3)

...
WHERE  (roles & B'001') <> 0::bit(3);

您可能对此相关答案感兴趣,该答案演示了在booleanbit stringinteger之间进行转换的多种方式:
Can I convert a bunch of boolean columns to a single bitmap in PostgreSQL?

请注意,将数据存储为integer可以节省一些空间。 integer需要 4个字节,最多需要32位信息,而 - 我引用manual at said location

  

对于每组8位,加5或<5>,位字符串值需要 1字节   8字节开销,具体取决于字符串[...]

的长度