这种架构设计好吗?

时间:2009-07-02 15:10:42

标签: sql sql-server sql-server-2005

我继承了一个系统,该系统存储数据库中某些表中某些字段的默认值。应用程序中使用这些默认值来预填充控制值。因此,基本上,数据库中每个表中的每个字段都可能具有默认值。之前的开发人员决定将这些值存储在一个具有键/值对组合的表中。由源表+字段名称(作为varchar)表示的键,以及作为varchar字段的默认值。然后,业务层将varchar字段强制转换为适当的数据类型。

不知何故,我觉得这很脆弱。虽然应用程序按预期工作,但设计中似乎存在缺陷。

有关如何更早处理此要求的任何建议?现在有什么可以做的让它更健壮吗?

编辑:我应该定义“默认”一词的含义。这与表中字段的默认值无关。相反,它是前端应用程序将使用的默认值。

9 个答案:

答案 0 :(得分:4)

那个架构设计很好。我已经看到它在商业应用程序中使用,我也在我自己的一些应用程序中使用它,用户需要能够更改应用程序中字段的默认值或其他参数(限制,允许的字符等)或者应用程序允许用户添加新字段以便在应用程序中使用。

将它放在一个表中(不是每个表的单独的默认表)可以保护它免受它支持的表中的模式更改。这些模式更改在此模型中变为简单的配置更改。

单个表可以很容易地封装在一个Class中作为“默认”配置对象。

一些一般建议: 当你继承一个工作系统并且不理解为什么某些东西按照它的方式设计时 - 问题很可能是你的理解,而不是系统。如果没有损坏,不解决它

我建议的唯一改进的具体建议(如果有必要): 您可以将新的SQLVARIANT字段用于值而不是varchar - 它可以包含任何常规数据类型 - 您需要添加支持,以便在使用该值时将它们转换为正确的数据类型。

答案 1 :(得分:3)

更好的方法是使用SQL Server内置DEFAULT约束。 e。

CREATE TABLE Orders
(
    OrderID int IDENTITY NOT NULL,
    OrderDate datetime NULL CONSTRAINT DF_Orders_OrderDate DEFAULT(GETDATE()),
    Freight money NULL CONSTRAINT DF_Orders_Freight DEFAULT (0) CHECK(Freight >= 0),
    ShipAddress nvarchar (60) NULL DF_Orders_ShipAddress DEFAULT('NO SHIPPING ADDRESS'),
    EnteredBy nvarchar (60) NOT NULL DF_Orders_EnteredBy DEFAULT(SUSER_SNAME())
)

答案 2 :(得分:3)

现在重构架构会有风险和破坏性,所以我不推荐它(除非你绝对需要这样做来解决一些紧迫的问题,但是从你说的看起来不像你那样)。

如果您从头开始进行设计,我建议每个实际表使用一个默认表,其中一行记录默认值及其实际列名和类型。有几个小桌子让一些DBA感到害怕,但根据我的经验,它并没有真正的性能影响,而且确实可以让系统更健全,更强大。

如果您想要使用SQL自己的DEFAULT子句,请务必明确命名,否则在默认更改可能是一个doozy时更改它们。就个人而言,我喜欢将默认值与模式的元数据分开,特别是在一个系统中,更新或调整默认值是比元数据/模式更改的重大任务更常见且应该是无害的操作!

答案 3 :(得分:2)

如果要求是给定控件的默认选择是可配置的并且“应用程序按预期工作”那么我没有看到问题。你没有详细说明设计中的“缺陷”。

答案 4 :(得分:1)

如果你想(并且应该!)在数据库上使用默认值,我会强烈敦促使用任何字段上可用的内置DEFAULT约束。只有这一点才能真正保证正常工作 - 其他任何东西都是最好的黑客解决方案......

CREATE TABLE 
  MyTable(ID INT IDENTITY(1,1),
          NumericField INT CONSTRAINT DF_MyTable_Numeric DEFAULT(42),
          StringID VARCHAR(20) CONSTRAINT DF_MyTable_StringID DEFAULT 'rubbish',
      .......)

等等 - 你明白了。

只要学习这句口头禅:干 - 不要重复自己 - 不要重新发明那些已经存在且经过大量测试和使用的东西 - 只需使用它。

马克

答案 5 :(得分:1)

如果是UI默认情况 - 会出现以下问题。

  • 您的架构的“动态”或通用程度如何?相同的模式是否支持多个前端 - 即Db表中的同一列支持2个前端 - 每个都有多个默认值?
  • 多个应用使用您的数据库?在这种情况下,DB中定义的默认值仍然可以帮助
  • 可以查询数据字典以获取每列的默认信息。
  • 如果UI字段没有相应的db-column,那么在这种情况下您的当前实现将是合理的
  • 一个缺点是需要更多代码来处理和使用此表。
  • 如果是一次性应用程序并且这个默认的“智能”并未在多个应用程序中使用 - 这是一个考虑因素
  • 它更像是一种“框架式”的事情 - 尽管我说它非常不标准,并且会在网络层上完成。

答案 6 :(得分:1)

我认为这里真正的答案在很大程度上取决于这些默认值的变化频率。如果在设计数据库时将默认值设置为一次,则DEFAULT约束是有意义的。如果一些非技术人员需要每隔几个月更换一次,我真的很喜欢这个设计。

当它变得脆弱时,如果列名或数据类型与默认值表中的默认值不匹配。如果您编写一个仔细的界面来管理Defaults表值,这应该不是问题。

答案 7 :(得分:0)

如果您希望将应用程序默认值与数据分开,那么这个想法(不一定是实现)是有意义的,允许不同的应用程序具有不同的默认值。

这通常是件好事,因为许多数据库不可避免地产生辅助应用程序(导入作业,如果不是其他任何东西),你不需要相同的默认值(或任何默认值);原则上,默认表可以支持这一点。

我认为这种实现不太理想的是,虽然默认值是MOSTLY数据驱动的,但调用应用程序要么需要自己的默认值,如果默认值没有在表中指定或终止。

如果使用前者,当您尝试追踪错误时,这可能会引入一些令人头疼的问题,特别是如果您没有良好的审核表,可以跟踪哪些用户/应用程序插入/更新了哪些行表。

免责声明:我通常认为列应该是NULLable并且没有默认值,除非它从数据的角度来看是绝对有意义的(id /主键,自定义时间戳等)。如果列永远不应为NULL,则引入禁止NULL的约束,而不是具体的默认值。

答案 8 :(得分:0)

如果默认值表让你烦恼,这里有一些值得深思的东西:

不是坚持关于varchar(max)或者铸造字符串或键/值表的教条 - 一个好方法是问什么是更好的解决方案?

根据您的描述,该表似乎包含几行,并且只有两列:键和值。

我应该问 - 这个表中的数据是否来自管理UI?也许这就是原设计决策背后的原因。

如果类型安全性存在问题,您可以考虑存在“类型”列并分析代码需要如何更改。

在你真正分析为什么以这种方式实施系统之前,我不会跳到“好”或“坏”的结论。