在SQL Server数据库中使用单行配置表.馊主意?

Dav*_*och 141 sql configuration database-design relational-database

在开发购物车应用程序时,我发现我需要根据管理员的偏好和要求保存设置和配置.此信息可以是公司信息,运输帐户ID,PayPal API密钥,通知首选项等.

创建一个表来在关系数据库系统中存储单行似乎非常不合适.

存储此信息的适当方法是什么?

注意:我的DBMS是SQL Server 2008,编程层是用ASP.NET实现的(在C#中).

adr*_*nks 182

我过去曾做过两种方式 - 单行表和键/值对表 - 每种方法都有正面和负面.

单行

  • positive:值以正确的类型存储
  • 积极的:代码处理更容易(由于上述原因)
  • positive:可以单独为每个设置指定默认值
  • 否定:添加新设置需要更改架构
  • 否定:如果有很多设置,表格会变宽

键/值对

  • 肯定:添加新设置不需要更改架构
  • positive:表模式很窄,额外的行用于新设置
  • 否定:每个设置都有相同的默认值(null/empty?)
  • 否定:一切都必须存储为字符串(即.nvarchar)
  • 否定:在处理代码中的设置时,您必须知道设置的类型并进行转换

单行选项是迄今为止最容易使用的选项.这是因为您可以在数据库中以正确的类型存储每个设置,而不必在代码中存储设置的类型以及它们的查找键.

我关注使用这种方法的一件事是在"特殊"单行设置表中有多行.我通过(在SQL Server中)克服了这个问题:

  • 添加一个默认值为0的新位列
  • 创建检查约束以确保此列的值为0
  • 在位列上创建唯一约束

这意味着表中只能存在一行,因为位列必须具有值0,但由于唯一约束,只能有一行具有该值.

  • +1,感谢您将表格限制为单行的想法 (22认同)
  • 在实施单行解决方案之后,有一件事真的会破坏你的一天,那就是当你后来的任务是"让我们跟踪每个值的最后一次改变以及谁改变它......" (19认同)
  • 单行正:可以在某些列上定义FK! (16认同)
  • 您始终可以使用类型标识符执行键/值对,以确定哪个列的值类型具有值.这为您提供了两全其美的优势,您可以使用存储过程在需要时获取值. (8认同)
  • 单行解决方案的另一个优点,我在一个案例中发现:我有一个为一个客户端构建的应用程序,带有一个用于"设置"的单行表.我后来有两个其他客户想要使用相同的应用程序,但想要不同的设置:我只需要在表中添加一个"client_id"PK,以便为每个客户端维护一组单独的设置.(这是当你意识到这些"设置"实际上只是你尚未建模的更高级别实体的属性.) (6认同)
  • 我们在LOB应用程序中执行单行操作.这些值都是正确的类型,这使得在应用程序中使用它们变得更加简单.我们的模式与应用程序一起进行了版本控制,因此对配置设置的更改将像任何应用程序修订一样进行管理. (5认同)
  • 关键值负值:如果您想从“关键值/值”表中进行报告,则需要为每个要显示的属性将其联接一次。大于3,并且会缓慢爬行。如果您永远不想从该表中进行报告,并且一次只查找或编写单个属性,并且它是一个相对较小的表,则可以使用EAV模型,否则使用单行表。 (2认同)
  • @DaveMateer:为什么会有问题?您始终可以创建另一个“日志”表并使用触发器。 (2认同)
  • 单行否定:虽然我更喜欢单行,但在某些情况下,如果您尝试从繁忙系统上的多个位置更新设置,您可能会遇到行级锁定情况,因为 SQL 会在更新时锁定整行。不是不可逾越的问题,只是一个评论。 (2认同)

Otá*_*cio 10

您应该创建一个表,其中包含信息类型和信息值的列(至少).这样,您可以避免每次添加新信息时都必须创建新列.

  • 为什么创建新列会有问题?我知道有些情况下开发人员必须避免它,因为更新SQL模式的政治问题,但在问题中没有提到这一点. (4认同)

And*_*mar 6

单排工作正常; 它甚至会有很强的类型:

show_borders    bit
admin_name      varchar(50)
max_users       int
Run Code Online (Sandbox Code Playgroud)

一个缺点是它需要架构更改(alter table)来添加新设置.一种替代方法是规范化,最终得到如下表:

pref_name       varchar(50) primary key
pref_value      varchar(50) 
Run Code Online (Sandbox Code Playgroud)

这有弱类型(一切都是varchar),但添加一个新设置只是添加一行,你可以只使用数据库写访问.


E.J*_*nan 5

就个人而言,如果可行的话,我会将其存储在一行中。将其存储在 SQL 表中的过度杀伤力?可能,但这样做并没有真正的危害。