【问题标题】:SQL table with a single row? [closed]单行的 SQL 表? [关闭]
【发布时间】:2010-11-15 13:16:02
【问题描述】:

在数据库中只有一行的表有什么意义(如果有的话)?

注意:我不是在谈论表格中只有一行的可能性,而是当开发人员故意制作一个旨在始终只有一行的表格时。

编辑:

销售税的例子很好。

我刚刚在一些代码中观察到我正在查看三个不同的表,其中包含三种不同类型的证书(a la SSL),每一个都有一行。我不明白为什么不把它做成一张大桌子;我想我错过了什么。

【问题讨论】:

  • 如果可以,何不亲自请开发者解释?
  • 另外,这不会导致“编程气味”吗?由于数据库中没有可用于指定单行表的机制,是否有可能不小心在表中放置两个元素并在以后查询时使用不正确的数据?
  • @Jeremy:您可以滥用大多数 RDBMes 中的机制来强制执行 1 行限制 - 例如定义主键(或唯一键)列,然后在同一列上添加检查约束只允许一个值。不过,这并不令人愉快
  • 我认为这是一个有效的问题,它是一个“为什么这种方法有好处”,这是一个很好的问题类型。
  • 单行表的一个论点是您可以存储配置数据,然后还可以在 SQL 中进行数据建模。您的配置选项之一有外键?没问题!

标签: sql schema


【解决方案1】:

模拟数据库系统不提供的某些功能有时会很有用。例如,我正在考虑 MySQL 中的序列。

【讨论】:

  • 为什么不呢?许多开发人员使用的表看起来像这些表来存储 settings 例如对于脚本,我认为它是个好主意并且更安全,而不是 xml 文件,因为它可读
【解决方案2】:

对于某些事情,您只需要一行 - 通常是系统配置数据。例如,“当前销售税率”。这可能会在未来发生变化,因此不应进行硬编码,但您通常只会在任何给定时间需要一个。这种数据需要在数据库中,以便查询可以在计算中使用它。

【讨论】:

  • 那你有没有把每个州都当成一列呢?即:从 CurrentSalesTaxRate 中选择加利福尼亚?
  • 我不太喜欢这个,例如在加拿大,我们的国家销售税在过去 5 年中发生了两次变化,省级销售税也在发生变化。因此,最好使用带有税率/税率/生效/到期日期的销售税表。
  • 对于简单的系统配置数据,我会考虑一个键值对表,每个配置项都有一行。
  • 如果只有一个配置项,那么表中就只有一行:-)
  • @JasonMusgrove 然而,即使是一组简单的系统配置数据也很容易包含不同类型的值。例如整数、字符串和布尔值。当然我们不能为每个不同的值类型都创建一个新的键值表,所以我们回到单行表。
【解决方案3】:

这不一定是个坏主意。

如果您有一些全局状态(例如布尔值)想要存储在某个地方怎么办?并且您希望您的存储过程能够轻松访问此状态?

您可以创建一个具有主键的表,其值范围仅限于一个值。

【讨论】:

    【解决方案4】:

    当要求开发人员创建一个配置表来存储需要持久保存而不经常更改的数据的名称-值对时,我曾看到过类似的情况。他最终创建了一个单行表,其中每个配置变量都有一列。我不会说这是一个好主意,但我当然可以理解为什么开发人员按照他的指示这样做了。不用说它没有通过审查。

    我刚刚在一些代码中观察到我正在查看三个不同的表,其中包含三种不同类型的证书(a la SSL),每一个都有一行。我不明白为什么不把它排成一排;我想我错过了什么。

    这听起来不像是好的设计,除非有一些你不知道的重要细节。如果有三条信息具有相同的约束、相同的用途和相同的结构,它们应该存储在同一个表中,99% 的时间。这是表格的主要用途。

    【讨论】:

    • 是的,这也是我的印象,但我认为“singleton”表可能有一些特殊的加速(singleton 在这里可能不是正确的词,但你明白了)跨度>
    • 正确的聚集索引不会提供任何提升。
    • Welbog 考虑到你的案例的限制,你提到什么是好的设计选项?
    【解决方案5】:

    除非在表上有插入约束,否则版本控制的时间戳听起来是个坏主意。

    【讨论】:

      【解决方案6】:

      在数据库中只有一行的表有什么意义(如果有的话)?

      关系数据库将事物存储为关系:满足某种关系的数据元组。

      就像这个:“VAT of 这个百分比现在在我的国家有效”。

      如果只有一个元组满足这个关系,那么是的,它将是表中唯一的一个。

      SQL不能存储变量:它可以存储一个由1元素组成的集合,这是一个单行表。

      另外,SQL 是一种基于集合的语言,对于某些操作,您需要一个只有一行的假集合,例如选择一个常量表达式。

      您不能在Oracle 中凭空出现SELECT,您需要一个FROM 子句。

      Oracle 有一个伪表dual,它只包含一行和一列。

      很久以前,它曾经有 行(因此得名 dual),但在升级到版本 7 的途中某处丢失了第二行。

      MySQL 也有这个伪表,但是MySQL 能够在没有FROM 子句的情况下进行选择。不过,当您需要一个空行集时,它还是很有用的:SELECT 1 FROM dual WHERE NULL

      我刚刚在一些代码中观察到我正在查看三个不同的表,其中包含三种不同类型的证书(例如SSL),每个表都只有一行。我不明白为什么不把它做成一张大桌子;我想我错过了什么。

      当一次需要所有三个证书时,这可能是一种“要么全部要么失去”的场景:

      SELECT  *
      FROM    ssl1
      CROSS JOIN
              ssl2
      CROSS JOIN
              ssl3
      

      如果缺少证书,则整个查询不返回任何内容。

      【讨论】:

      • 我绝对看不到这里的 coss join 模式,但这是一个好点。
      • @Jeremy:如果您不需要任何其他条件,除了存在或不存在一行,CROSS JOIN 就是您所需要的。
      【解决方案7】:

      具有单行的表可用于存储所有数据库用户共享的应用程序级设置。例如“最大允许用户数”。

      【讨论】:

        【解决方案8】:

        有趣...我问自己同样的问题。如果您只想存储一些简单的值,而您唯一的存储方法是 SQL 服务器,那么这几乎就是您必须做的。如果我必须这样做,我通常最终会创建一个包含多列和一行的表。我见过一些商业产品也能做到这一点。

        【讨论】:

          【解决方案9】:

          过去我们使用过单行表(不经常)。在我们的案例中,此表用于存储可通过 Web 界面更新的系统范围的配置值。我们本可以采用简单的名称/值表,但最终客户端更喜欢单行。我个人更喜欢后者,但这确实取决于偏好,特别是如果这张桌子永远不会与另一张桌子有任何关系。

          【讨论】:

          • 单个表可能比名称值表更好。呃,如果有任何替代方案,我一想到有人使用其中一种,我就感到畏缩,因为它们的性能可能很糟糕。
          【解决方案10】:

          如果您的数据库是您的应用程序,那么存储实现业务逻辑的存储过程可能需要的配置数据可能是有意义的。

          如果您的应用程序可以使用文件系统来存储信息,那么我认为使用数据库与 XML 或平面文件相比没有优势,除非大多数开发人员现在更加精通在使用 SQL 存储和检索数据而不是访问文件系统方面。

          【讨论】:

            【解决方案11】:

            在我继承的一个项目中有这样一张桌子。它用于配置数据,给出的原因是它用于非常简单的查询:

            SELECT WidgetSize FROM ConfigTable
            SELECT FooLength  FROM ConfigTable
            

            好吧好吧。我们转换成一个通用的配置表:

            ID  Name  IntValue StringValue TextValue
            

            这很好地满足了我们的目的。

            【讨论】:

              【解决方案12】:

              我真的不明白为什么这是最好的解决方案。仅拥有某种配置文件会更有效,该配置文件将包含表中一行中的数据。连接到数据库并查询一行的成本会更高。但是,如果这将是数据库逻辑的某种配置。然后根据您使用的数据库类型,这会更有意义。

              【讨论】:

              • 当这些设置必须由非开发人员管理时,使用单行表来存储系统设置更有意义。
              【解决方案13】:

              我为此 http://github.com/Squeegy/rails-settings/tree/master 使用了非常棒的 rails-settings 插件

              它真的很容易设置并且提供了很好的语法:

                Settings.admin_password = 'supersecret'
                Settings.date_format    = '%m %d, %Y'
                Settings.cocktails      = ['Martini', 'Screwdriver', 'White Russian']
                Settings.foo            = 123
              

              想要所有设置的列表吗?

                Settings.all            # returns {'admin_password' => 'super_secret', 'date_format' => '%m %d, %Y'}
              

              为应用的某些设置设置默认值。这将导致定义的设置返回指定值,即使它们不在数据库中。使用以下内容在 config/initializers/settings.rb 中创建一个新文件:

              Settings.defaults[:some_setting] = 'footastic'
              

              【讨论】:

              • 我对我的 sql server db 中的设置做同样的事情! =)
              【解决方案14】:
              CREATE TABLE VERSION (VERSION_STRING VARCHAR2(20 BYTE))
              

              ?

              【讨论】:

                【解决方案15】:

                我使用 SQLite 数据库中的单个数据作为动态网页中的计数器。这是我能想到的使它成为线程安全(或者准确地说是进程安全)的最简单方法。但我不确定这是否是个好主意。

                【讨论】:

                  【解决方案16】:

                  单行就像一个单例类。目的:控制或管理其他过程。

                  单行表可以充当临界区或确定性自动机(一种基于行值的调度程序)

                  在 COMPANY_DESCRIPTION 表中使用完整的单行,以获取有关该公司的一致数据。使用完整的公司信件和地址。

                  单行用于包含实际值,如增值税或日期或时间等。

                  【讨论】:

                    【解决方案17】:

                    我认为处理这些场景的最佳方法是,而不是使用数据库,而是使用配置文件(通常是 XML)或制作您自己的配置文件,以便在应用程序启动期间读取。编写读取文件的代码只需几分钟。

                    这里的好处是不会意外地为同一个 XML 变量添加额外的值,而且它非常适合测试,因为您不需要编写大量代码来测试不同的输入,只需一个简单的更改到文本值并重新运行应用程序。

                    【讨论】:

                      【解决方案18】:

                      一个用途可能是存储数据库的当前版本。

                      如果要为架构更改存储数据库版本,则它需要驻留在数据库本身中。

                      我目前正在分析架构并进行相应更新,但我正在考虑转向版本控制。除非有人有更好的主意。

                      我使用 vb.net 和 sql express

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-07-15
                        • 2014-12-17
                        • 2010-10-20
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多