去域还是不去域


15

SQL92和SQL99标准定义了DDL构造。并非所有的数据库都支持此功能,或者并非所有数据库都支持此名称(例如,SQL Server具有用户定义的类型)。CREATE DOMAIN

这些允许人们定义要在其数据库中使用的约束数据类型,以简化和执行与允许值有关的规则。这种数据类型可用于列声明,存储过程和函数的输入和输出等。

我想知道:

  • 人们实际上在他们的数据库设计中使用域吗?
  • 如果是这样到什么程度?
  • 它们有多有用?
  • 您遇到了什么陷阱?

我正在尝试评估在将来的数据库开发中使用它们的可行性。


1
我也想知道这一点...我很想听听人们怎么说。
maple_shaft

Answers:


2

照常...

这取决于

您是否在一个以上的地方使用了一个域实体,否则需要大量的精力和/或冗余的约束和行为来进行本地支持?

如果是这样,请移开域。如果没有,请不要打扰。

基于上述启发式方法,我发现有必要在SQL Server中仅创建一次用户定义的类型。我什至不记得它是什么了-但是它节省了很多工作。


5

作为SQL Server和C#的用户,我没有在数据库中使用用户定义类型,因为我在应用程序方面更加强大。在发生诸如LINQ to SQL和Entity Framework之类的ORM之后,我对服务器功能的使用减少了很多。

例如,基于.NET的全球化功能,我使用CLR集成将某些DateTime转换功能加载到SQL Server,以将公历日期时间转换为其他格式。但是现在,情况有所不同,我不再这样做了。我只需要在应用程序层中加载数据并进行转换即可。

因此,经过将近4年的编程和检查我能想到的所有团队之后,我发现没有使用用户定义类型的示例。我也没有在许多.NET博客中看到它的实际效果。

虽然这并不意味着人们不使用数据库域,但肯定意味着至少使用数据库域并不常见。


“我没有在数据库中使用用户定义类型,因为我在应用程序方面更强大”:所以您使用约束代替了吗?我不明白,从应用程序角度来看有什么不同?
阿森尼·穆尔琴科2011年

例如,@ MainMa,我不在数据库层中创建Student类。我只创建一个具有所有原始数据类型(如整数和字符串)的学生表,然后使用ORM将任何记录映射到应用程序中的对象。
Saeed Neamati 2011年

明白了 你是对的。
阿森尼·穆尔琴科2011年

3

关于堆栈溢出已经有详细的答案。我大都同意,但不同意给出的例子,我引用:

“例如,我定义了一个“ GenderType”(char(1),不可为空,持有“ M”或“ F”),以确保“性别”字段中仅允许使用适当的数据。”

就个人而言,我觉得更舒适地设置char(1)类型并在列上定义约束。当违反约束时,我确切地知道在哪里可以找到我做错了什么。它也比用户定义的类型更知名,因此对于初学者来说,仅使用约束的数据库将更容易理解。

当然,这只是个人观点。其他人会说in ('M', 'F')约束不是自记录的,对于发现数据库的新开发人员来说可能是非常模糊的。

IMO,将用户定义的类型用于更复杂的类型,并将约束用于基本内容。另外,当您无法轻松找到类型的显式名称时,就有可能使约束更合适。


雌雄同体呢?
Wyatt Barnett

还是两性?还是超人?
Broam

1

我自己没有使用此功能,但我想您需要确保:

  1. 如果您的数据库由单个系统使用,则最好不要使用此功能,并在您的业务层或等效层中添加检查逻辑。这样可以为您提供更大的验证灵活性(例如使用正则表达式),并且可以将所有验证逻辑封装在一个地方。如果您的数据库由多个系统共享,则可以使用非常适合此任务的触发器。

  2. 我不确定UDT是否允许您自定义遇到验证错误时返回给客户端的错误消息。

  3. 如果同一验证规则适用于多列,则UDT非常有用。我认为,在具有规范化数据库设计的业务应用程序中,这并不常见。

您可能对检查“ [SQL Server]用户定义的类型有什么意义?”感兴趣。博客文章。


1
+1为第三点。一次又一次地写相同的约束不是最好的事情,特别是当约束可能随时间变化时,需要在多个位置进行更改。
阿森尼·穆尔琴科2011年

0

当您说“并非所有数据库都支持此功能”时,我认为一种更好的放置方式如下:

每个主要数据库都支持此功能,因为它们广泛支持触发器,功能和其他高级功能。

这使我们得出结论,它是高级SQL的一部分,并且在某些时候是有意义的。

Do people actually use domains in their database designs?

由于所需的覆盖范围广(考虑到运算符,索引等),可能性较小

If so to what extent?

再次,尽可能地限制,如果将现有的类型与一些附加的定义的逻辑(例如,检查等)结合起来可以解决问题,为什么走那么远?

How useful are they?

很多。让我们花一秒钟的时间来考虑一下像MySQL这样不太好的DBMS,我之所以在此示例中选择它是出于以下原因:它对inet(IP地址)类型缺乏良好的支持。

现在,您要编写一个主要关注范围和所有此类IP数据的应用程序,并且受制于默认类型及其有限的功能,您将编写其他功能和运算符(例如postgreSQL本身支持的功能和运算符)例如),或针对所需的每种功能编写更复杂的查询。

在这种情况下,您可以轻松地证明花费在定义自己的函数上的时间(PostgreSQL中的inet >> inet:range运算符中包含的range)。

到那时,您已经证明扩展数据类型支持是合理的,定义新数据类型仅需执行另一步。

现在回到具有真正好的类型支持但没有unsigned int ..的PostgreSQL,因为您确实关心存储/性能(谁知道...),所以您还需要添加它以及运算符-尽管这当然是大多数现有int运算符的派生。

What pitfalls have you encountered?

到目前为止,我还没有解决这个问题,因为我还没有一个项目既需要时间又需要时间证明。

我能看到的最大的问题是重新发明轮子,在“安全”层(db)中引入错误,不完整的类型支持,直到CONCAT(cast * AS varchar)失败后几个月,您才会意识到,因为您没有定义强制类型转换(newtype为varchar),等等。

有关于“不常见”等的答案。肯定是并且应该不常见(否则,这意味着dbms缺少很多重要类型),但是另一方面,应该记住一个(好的)db是ACID兼容的(与应用程序不同),并且与一致性相关的任何内容都最好保留在其中。

在许多情况下,业务逻辑是在软件层中处理的,并且可以在SQL中完成,这更安全。应用程序开发人员倾向于在应用程序层中感到更自在,并经常避免使用SQL实施更好的解决方案,这不应被视为良好实践。

UDT可能是优化的良好解决方案,另一个关于使用char(1)的m / f类型的答案给出了一个很好的例子。如果它是UDT,则它可以是布尔值(除非我们想提供第三和第四种选择)。当然,由于列的开销,我们都知道这并不是真正的优化,但是存在可能性。


并非所有数据库都支持特定功能(DOMAIN)。是的,使用触发器,约束和函数可以模拟它,但这并不能使其成为受支持的功能。
Oded

每个主要数据库都支持此功能,因为它们广泛支持触发器,功能和其他高级功能。一些真正的功能轻巧/ cr脚的人则不会,而使用它们的人都不会在乎,因为它们的局限性超出了用户特定的类型;)
Morg。

0

从表面上看,UDT是一个很好的概念。它们使您能够真正规范化数据库(例如,当您有两个相互依赖的列时),并且还可以封装与您的新类型相关的任何逻辑。

实际上,您今天支付的价格过高。显然有开发开销,但除此之外,您还会失去各种ORM和报告工具的支持,从而使解决方案的整体复杂性大大提高。没有太多开发人员对UDT非常熟悉,而且我从未见过在示例之外使用过托管UDT。

最好是作为UDT(如果尚不存在)完成的类型的最佳示例之一hierarchyidMSDN链接)。为了保持效率,它以二进制格式存储其值(与通常的varchar自定义实现相反),如果没有该类型的函数,将很难维护。与外部函数相反,该类型提供的10种左右方法也最好作为该类型的一部分提供。在这种情况下,我将考虑使用自定义托管的UDT-通过提供有效而简洁的实现作为单独的类型,可以显着提高收益。


0

更实用的问题/答案。贵公司允许使用它吗?

您的公司与几个处理不同DDL的DBSQL品牌合作吗?

每个数据库品牌都可能提供良好的附加功能,例如用户定义类型,但是,如果您的公司使用多个数据库,则可能会遇到非标准功能。

如果公司仅由您自己决定,或者您可以决定要使用哪些数据库和功能,则可以使用DDL

我已经在几个项目中使用了用户定义类型,但是我应该坚持使用更多标准功能,因为我们必须处理多个数据库。(s)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.