【问题标题】:Constraint on bitwise column behaving like C# enum flags约束按位列的行为类似于 C# 枚举标志
【发布时间】:2014-01-22 06:51:47
【问题描述】:

您如何建议对映射 C# 标记枚举值的列实施约束?

这里有一个很好的管理按位运算的解决方案: SQL Server Bitwise behave like C# Enum Flags

此外,我想限制此列中输入的值。该枚举现在包含大约 10 个成员,将来可能会增加。

【问题讨论】:

    标签: sql-server bitwise-operators


    【解决方案1】:

    如果您有一个包含 10 个数字的按位枚举,那么它们的值将是 1 到 512,2 的幂。因此范围可以是 0 到 1023。添加这样的约束:

    CREATE TABLE sample
       (
       id       INT PRIMARY KEY,
       flags    INT,
       CONSTRAINT chk_flgs CHECK (flags BETWEEN 0 and 1023)
       )
    

    但是,我强烈警告不要这样做。关系数据库旨在允许以各种方式访问​​数据并轻松地对数据运行查询。按位运算符在 SQL 中效率不高。想一想您想列出所有匹配标志的情况吗?使用枚举值创建一个查找表并在您的源和查找表之间添加一个交叉引用表会更加规范化。

    上面的例子会变成这样:

    CREATE TABLE Flags
        (
        FlagID  INT PRIMARY KEY, -- When inserted, match enum value
        FlagName    nvarchar(50)
        );
    
    CREATE TABLE SampleS
        (
        SampleID    INT PRIMARY KEY
        );
    
    CREATE TABLE Xref_Sample_Flags
        (
        SampleID INT,
        FlagID INT,
        CONSTRAINT FK_SampleID FOREIGN KEY (SampleID) REFERENCES Sample (SampleID),
        CONSTRAINT FK_FlagID FOREIGN KEY (FlagID) REFERENCES Flags (FlagID)
        );
    

    更多表,但从长远来看更易于维护和查询。

    【讨论】:

    • 为什么觉得他们效率不高?我没有看到任何问题。我相信使用按位运算符的最大优势始于设计。我有一张包含多个组的用户表。我必须在组和用户表之间设计一对多的表关系,并选择所有这些行来找出每个用户的所有组。而对于按位,我只需要使用按位运算逻辑在用户中选择一个字段。
    • @GregoryBologna 以及如何在特定组中搜索用户?您需要遍历每一行并且不能使用索引。如果您没有看到任何问题,那是因为您没有过滤或加入该字段,或者您的数据量可以忽略不计。做任何古怪的事情来避免在关系数据库中创建表是非常糟糕的做法。关系数据库应该有表,这些表应该遵循规范化标准。如果这不是您想要的,那么您可能使用了错误类型的数据库。
    • 这不是“古怪”。您在组上使用一个字段,每个组都有一个位值,例如 2. 4. 8, 16 等。然后您对用户表执行按位数学运算,因此如果用户 A 属于组 2 和 8,则user_group_id 将是 10。然后在连接上使用按位数学将返回 2 和 8 的组行。加入 `users u on(10 & u.user_group_id) = 10 或 on the where 10 = (10 & u.user_group_id)。这是一个关于这样做的非常好的视频。 wildermuth.com/2021/03/28/…
    • @GregoryBologna 当然欢迎您提出意见。我的是...该视频正在讨论 C# 中的按位字段。这没什么不好。用 SQL 做这件事很疯狂。您是否在具有数千万行的两个表上使用了按位联接?查询计划是什么样的?这将是一个全表扫描。每次。如果你愿意,你可以保留你的意见,但如果是我团队中的某个人,他们就不会在我团队中待太久了。它表明了对关系数据库如何工作以及如何优化它们的根本误解。
    • 你有意见,不是我。如果在 SQL 中使用按位运算是错误的,我不会讨论这个问题。需要明确的是,我的示例没有讨论在数百万行的表上使用它。也许这就是我们碰头的地方?成为一名称职的软件工程师的要点之一是解决问题的能力。位运算符是核心计算过程的基础,可以适应解决问题,例如存在于组中的返回用户,而不是创建冗余的一对多表。表仍然支持 ref integ。当它有一个二进制操作的字段时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多