【问题标题】:sql boolean datatype alternativessql 布尔数据类型替代方案
【发布时间】:2011-03-18 20:41:28
【问题描述】:

在哪些情况下你会使用一个单独的表的外键而不是使用布尔值(即 SQL Server 中的 BIT)

例如,您是否会替换此表中的以下两个布尔值:

engine_sensors
--------------
id (int, primary key)
name (varchar(50))
fault_code (int)
display_warning (boolean) /* if fault show driver a warning */
is_test_sensor (boolean) /* ignore this sensor in diagnostic checks */

例如此处的 display_warning 可能不会向驾驶员显示警告,但会向正在测试引擎的机械师显示警告。所以单独的表格是合适的。

is_test_sensor 可以替换为 sensor_type(FK 到 sensor_types 表),它具有 test,live 的类型。

【问题讨论】:

  • 什么 DBMS?为什么需要避免布尔类型?
  • DBMS 是 SQL Server,我知道你可以使用 BIT 类型。我想知道是否有人费心用外键替换它们来分隔表。

标签: sql database database-design types boolean


【解决方案1】:

这取决于您为什么要避免它。您可以只使用数字字段,其中 0 表示假,1 表示真。但不确定是否有任何好处。

【讨论】:

    【解决方案2】:

    如果字段模型为布尔值,我会将它们保留为布尔值。这就是它们存在的原因。

    我不会尝试在未来证明我的数据库设计(YAGNI 原则),您可以随时更改它。

    【讨论】:

    • 我认为你是对的,YAGNI 原则也会为我节省很多时间!但是,我对避免使用布尔值的想法很感兴趣。不是为了将来证明事情,而是为了更具体。例如 display_warning 布尔值很容易失去意义。那么将它链接到一个指定警告应该显示给谁的表会更好吗?
    • “代码很差,实体很丰富”。代码(即布尔标志)允许您只说是或否(例如:人结婚了吗?是或否)。实体允许你说任何话。例如:这个人与谁结婚?这个人什么时候结婚的?婚姻合同的法律条款是什么?等等等等。如有必要,实体允许您派生代码,但反之则不成立。
    • YAGNI 仅在事情有效地证明您确实不需要它的情况下才能节省您的时间(即真正节省时间)。但是,如果您需要它,那么毫无疑问,调用 YAGNI 最终会变成 COST 并且可能是巨大的。没有人可以在这里为您提供建议。根据具体情况使用您的最佳判断。试着弄清楚用户是否愿意并且能够提供那些你的布尔标志无法捕获的额外信息(他们是必须做这项工作的人,他们必须判断这样做的价值)。跨度>
    • 抱歉,我在这里重复了我之前的回复。为什么这个问题再次出现在我的列表顶部?
    【解决方案3】:

    首先,我想确认一下 Oded。如果您需要布尔值,您应该使用负责的列类型。

    但是,如果您必须存储非常不同的布尔值,有时使用存储在 INT、BIGINT 甚至 BINARY 列中的老式位掩码会更有用。

    【讨论】:

      【解决方案4】:

      如果您仍需要在代码中使用布尔值,在 SQL Server(0 或 1)中使用“位”将自动映射回 linq to SQL 中的布尔值。

      但是你没有说明什么数据库或者你为什么想要一个 bool 的替代品。

      【讨论】:

      • 感谢您的回复。它是一个 SQL Server 数据库,我知道您会使用一个位字段。我想知道用单独表的外键替换它们是多么糟糕的想法。
      【解决方案5】:

      您添加了一条信息

      '它是一个 SQL Server 数据库,我知道你会使用一个位字段。我想知道用单独表的外键替换它们是多么糟糕的想法'

      如果这对您寻求的解决方案很重要,您应该编辑您的原始问题并将其放入,以便更多人能够轻松找到它。

      但你还没有说为什么你想知道用 FK 替换它们。如果您告诉人们您的最终目标是什么或您想要实现的目标,他们更有可能提供一系列解决方案。

      很抱歉,我无法提出解决方案。外键(什么?)比布尔值好吗?相比?

      我认为您需要稍微澄清/重新构建您的问题。祝你好运。

      【讨论】:

      • 谢谢@Joshua。我想我一开始就不确定要问的问题是否正确。我试图重新编辑以获得更多我所要求的内容。
      • 我已经按照您的要求更新了我的解决方案。
      【解决方案6】:

      Np。现在我明白你的意思了(我想)。

      如果你问的是什么我认为你问的是不是,你可能想要对传感器表使用 FK 并列出传感器。这通常是我会做的......

      CREATE TABLE [SensorType](
      [Id] [int] NOT NULL,
      [Type] [int] NOT NULL,
          [DisplayWarningTo] [int] NOT NULL,
      [Description] [nvarchar](100) NULL,
      CONSTRAINT [PK_SensorType_Id] PRIMARY KEY (Id),
          CONSTRAINT [FK_SensorType_WarningReceivor] FOREIGN KEY (DisplayWarningTo) REFERENCES WarningReceivor(Id)    
       );
      
      CREATE TABLE [WarningReceiver](
      [Id] [int] NOT NULL,
      [Receiver] [int] NOT NULL,
      CONSTRAINT [PK_WarningReceiver_Id] PRIMARY KEY (Id)
       );
      
      ------
      
      INSERT INTO WarningReceiver(Id, Type) VALUES (1, 'Mechanic');
      INSERT INTO WarningReceiver(Id, Type) VALUES (2, 'Driver');
      
      INSERT INTO SensorType(Id, Type, DisplayWarningTo) VALUES (1, 'Rear sensor', 2);
      INSERT INTO SensorType(Id, Type, DisplayWarningTo) VALUES (2, 'Test sensor', 1);
      INSERT INTO SensorType(Id, Type, DisplayWarningTo) VALUES (3, 'Production sensor', 2);
      

      我倾向于不在这样的“类型”上使用标识列,而是指定我自己的 id,我将其直接映射到 C# 枚举常量,例如

      public enum SensorType
      {
          RearSensor = 1,
          TestSensor = 2,
          ProductionSensor = 3
      }
      

      然后在您的代码中,当您从数据库中提取引擎传感器时,您可以与您的枚举进行比较。例如

      var engine_sensor = // get engine sensor from db.
      if (engine_sensor == (int)SensorType.RearSensor)
      {
         // do something
      }
      else if (engine_sensor == (int)SensorType.TestSensor)
      {
         // display something to mechanic or whatever
      }
      

      我真的不知道你的应用程序域是什么,如果这没有意义,很抱歉。

      所以总结几点并尝试回答您的问题;

      • 是的,我确实认为你最好用 FK 的
      • 您可以将它们作为 int 列并在代码中定义传感器,就像我对枚举所做的那样
      • 我倾向于两者都做 --- 为代码中的强类型定义枚举和 ---创建一个外键表来完成我在数据库中的架构。出于两个原因,仍然值得拥有它; 1) 当在 management studio 或其他东西中编写 sql 查询并查看 engine_sensors 表并查看传感器类型的数字时,您可以加入 FK 表以查看传感器 是什么。让事情变得更简单

      最后,如果您有一个 FK 表,它会强制引用完整性并将您可以作为传感器类型输入的值限制为您在传感器类型表中定义的值。

      希望这会有所帮助。

      【讨论】:

        【解决方案7】:

        engine_sensors

        id(主键) 姓名 故障码

        display_warning_engine_sensors /* 如果故障显示驱动程序警告 */

        id(主键,FK 到 engine_sensors)

        test_sensors /* 在诊断检查中忽略此传感器 */

        id(主键,FK 到 engine_sensors)

        记住:代码很差,表格很丰富。不管这看起来多么矛盾:永远不要使用布尔值来表示真值信息。关系模型已经有一种表示真值信息的方法,那就是在某个关系中存在一些元组,它是某个 relvar 的值(用 SQL 术语来说:作为表中某行的存在)。

        您不能轻易地“扩展”布尔值来添加额外的功能,例如“仅当时间在 [x 小时 - y 小时] 范围内时才显示警告。

        【讨论】:

          【解决方案8】:

          关系理论可以帮助您回答这些问题。布尔值的去向(在所示的表中或在示例中描述的单独表中)应由布尔数据元素所依赖(和完全依赖)的内容来确定。

          例如,如果数据元素“display_warning”仅取决于传感器(您的表所描述的实体),则该列属于该表。但是,如果它依赖于其他实体(人 - 所有者或机械师 - 与传感器交互),那么它更适合属于不同的表,它可以完全且仅依赖于该表的主键。

          确保数据元素依赖于键(除了键)是通过数据的“规范化”来实现的。在这里的答案中包含很多内容,但是网络上有许多参考资料可以帮助您更全面地理解规范化。维基百科是一个很好的起点:

          http://en.wikipedia.org/wiki/Database_normalization#Normal_forms

          【讨论】:

            【解决方案9】:

            索引是避免布尔类型的原因之一。您不能索引布尔字段,因此如果您有很多记录并且经常搜索布尔字段,则使用单独的表可能会有所帮助。如果添加更多类型,单独的传感器类型表也更具可扩展性。如果特定传感器类型存在一对多关系,这也很有帮助。假设一个引擎需要三个特定类型的传感器。

            【讨论】:

              猜你喜欢
              • 2012-08-21
              • 2015-06-17
              • 1970-01-01
              • 2017-08-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-15
              相关资源
              最近更新 更多