您最有用的数据库标准是什么?

Raj*_*ore 44 sql database standards entity-relationship

我有一些想法,有些是我随着时间的推移积累的,但我真的想知道在建模数据库时是什么让事情顺利进行:

  1. 表名与主键名和描述键匹配
  2. 模式是功能区域
  3. 尽可能避免使用复合主键(使用唯一约束)
  4. Camel Case表名和字段名
  5. 不要使用tbl_为表添加前缀,或者使用SP_为procs添加前缀(不使用匈牙利语表示法)
  6. OLTP数据库应该至少在BCNF/4NF中

Ben*_*ter 19

  • 为具有相同前缀的类似目标存储过程命名,例如,如果您有3个存储过程用于Person.这样一来,人们的一切都集中在一个地方,您可以轻松找到它们,而无需查看所有过程来查找它们.
    • PersonUpdate
    • PersonDelete
    • PersonCreate
  • 当您拥有包含相关数据的表组时,对表执行类似的操作.例如:
    • InvoiceHeaders
    • InvoiceLines
    • InvoiceLineDetails
  • 如果您在数据库中可以选择模式,请使用它们.它看起来好多了:
    • Invoice.Header
    • Invoice.Line.Items
    • Invoice.Line.Item.Details
    • Person.Update
    • Person.Delete
    • Person.Create
  • 除非没有其他合理的方法来实现这一目标,否则不要使用触发器.
  • 给字段名称一个有意义的前缀,这样你就可以告诉他们来自哪个表而无需解释.这样,当您看到引用的字段名称时,您可以轻松地告诉它来自哪个表.
  • 对包含类似数据的字段使用一致的数据类型,即不将电话号码存储为一个表中的数字,将varchar存储在另一个表中.事实上,不要将它存储为数字,如果我遇到一个负面的电话号码我会生气.
  • 不要在表/字段名称中使用空格或其他模糊字符.它们应该完全是字母数字 - 或者如果我有我的druthers,除了下划线之外完全按字母顺序排列.我目前正在研究一个继承的系统,其中表和字段名称包含空格,问号和感叹号.让我想要每天杀死设计师!
  • 不要使用语法关键字作为对象名称,这会导致尝试从中检索数据的麻烦.我讨厌将对象名称包装为[index],这是两个不必要的字符我不需要输入该死的你!


HLG*_*GEM 13

有一点我还没有提到过:

切勿将数据库关键字用作对象名称.您不希望每次使用它们时都必须对它们进行限定

如果您在创建时拼错了某些内容,请在注意到后立即修复.不要花费数年时间来记住在这个表中UserName真的是Usernmae.当没有多少代码写入时,它更容易修复.

永远不要使用隐含连接(逗号语法),始终指定连接.

  • 隐含联接的+1,我已经厌倦了修复这样的查询. (2认同)

Raj*_*ore 11

将每个人的输入放在一个列表中.

命名标准

  • 模式按功能区域命名(产品,订单,运输)
  • 没有匈牙利表示法:对象名称中没有类型名称(没有strFirstName)
  • 不要将已注册的关键字用于对象名称
  • 对象名称中没有空格或任何特殊字符(Alphanumber + Underscore是唯一允许的内容)
  • 以自然方式命名对象(FirstName而不是NameFirst)
  • 表名应与主键名称和描述字段匹配(SalesType - SalesTypeId,SalesTypeDescription)
  • 不要用tbl_或sp_作为前缀
  • 按对象名称命名的代码(CustomerSearch,CustomerGetBalance)
  • CamelCase数据库对象名称
  • 列名应该是单数
  • 表名可以是复数
  • 为所有约束提供业务名称(MustEnterFirstName)

数据类型

  • 在表中使用相同的变量类型(Zip代码 - 一个表中的数字和另一个表中的varchar不是一个好主意)
  • 使用nNVarChar获取客户信息(姓名,地址)等,您永远不知道何时可以进入跨国公司

在代码中

  • 关键字始终在大写
  • 永远不要使用隐含连接(逗号语法) - 始终使用显式INNER JOIN/OUTER JOIN
  • 每行一个JOIN
  • 每行一个WHERE子句
  • 没有循环 - 用基于集合的逻辑替换
  • 对于别名而不是A,B,C使用简短形式的表名
  • 除非没有追索权,否则避免触发
  • 避免像瘟疫这样的游标(参见http://www.sqlservercentral.com/articles/T-SQL/66097/)

文档

  • 创建数据库图表
  • 创建数据字典

规范化和参照完整性

  • 尽可能使用单列主键.根据需要使用唯一约束.
  • 始终强制执行参照完整性
  • 避免ON DELETE CASCADE
  • OLTP必须至少为4NF
  • 评估每个一对多关系作为潜在的多对多关系
  • 非用户生成的主键
  • 构建基于插入的模型而不是基于更新
  • PK到FK必须是同名的(Employee.EmployeeId与EmployeeSalary.EmployeeId是同一个字段)
  • 除非有双连接(Person.PersonId连接到PersonRelation.PersonId_Parent和PersonRelation.PersonId_Child)

维护:运行定期脚本来查找

  • 没有表格的架构
  • 孤儿记录
  • 没有主键的表
  • 没有索引的表
  • 非确定性UDF
  • 备份,备份,备份


  • 始终如一
  • 修正错误,现在
  • 阅读Joe Celko的SQL编程风格(ISBN 978-0120887972)


cle*_*tus 10

我的Oracle标准是:

  • 关键字总是在大写;
  • 数据库对象名称始终为小写;
  • 下划线将替换空格(即,不会有任何常见的骆驼案例约定,例如,SQL Server);
  • 主键几乎总是被命名为'id';
  • 将强制执行参照完整性;
  • 整数值(包括表格ID)通常始终为NUMBER(19,0).这样做的原因是它将适合64位有符号整数,从而允许使用Java long类型而不是更笨拙的BigInteger;
  • 尽管将"_number"附加到某些列名称是错误的,但此类列的类型将是VARCHAR2而不是数字类型.数字类型保留给您进行算术运算的主键和列;
  • 我总是使用技术主键; 和
  • 每个表都有自己的密钥生成序列.该序列的名称为_seq.

对于SQL Server,唯一的修改是对数据库对象名称使用驼峰大小写(即PartyName而不是party_name).

查询将倾向于多行写入,每行有一个子句或条件:

SELECT field1, field2, field2
FROM tablename t1
JOIN tablename2 t2 ON t1.id = t2.tablename_id
WHERE t1.field1 = 'blah'
AND t2.field2 = 'foo'
Run Code Online (Sandbox Code Playgroud)

如果SELECT子句足够长,我将每行分割出一个字段.

  • 我们也为SQL Server使用"old_school_names".除此之外,我们的主要区别在于我更喜欢​​使用"tablename_id"而不仅仅是"id"作为主键 - 冗余,但不时有用; 它也意味着在大多数情况下,表A和表B之间的链接是在相同名称的列上进行的,例如purchase.purchase_type_id = purchase_type.purchase_type_id.我们还指定表名应该是单数,而不是复数("购买",而不是"购买"). (3认同)

Edw*_*ern 9

  • 命名所有约束


Sta*_* R. 8

不要忘记定期备份数据库.

  • 我会更进一步.**每日备份,每周恢复**.始终仔细检查您是否可以实际恢复备份,否则您将在困难时间发现备份不够好. (2认同)

Not*_*tMe 7

  1. 不要在字段名称中使用类型名称.年长的人会记住lpszFieldName的旧MS标准和随之而来的愚蠢.

  2. 使用符合常规语言约定的描述性字段名称.例如"FirstName"而不是"NameFirst"

  3. 字段名称中的每个单词都是大写的

  4. 没有下划线

  5. 不要使用普通的关键字,如"索引"

  6. 不要在ANYTHING前加上对象类型.例如,我们不使用tblCustomers或spCustomersGet.这些不允许良好的分类并提供零值.

  7. 使用模式定义数据库的单独区域.如sales.Customers和hr.Employees.这将摆脱人们使用的大多数前缀.

  8. 任何形式的循环都应该被怀疑.通常有一种更好的基于集合的方式.

  9. 对复杂的连接使用视图.

  10. 尽可能避免复杂的连接.拥有CustomerPhoneNumbers表可能更令人愉快; 但老实说,我们真的需要存储多少个电话号码?只需将字段添加到Customers表即可.您的数据库查询将更快,并且更容易理解.

  11. 如果一个表调用字段"EmployeeId",那么引用它的EVERY SINGLE TABLE应该使用该名称.它不需要被称为CustomerServiceRepId,因为它位于扩展表中.

  12. 几乎所有表都有"s"结尾.例如:客户,订单等.毕竟表中包含许多记录......

  13. 使用分析工具评估查询,索引和外键关系.甚至那些可能为你生成的.你可能会感到惊讶.

  14. 链接支持多对多关系的表在名称中都有链接表.例如,SchoolsGrades.通过表名告诉它它的作用非常容易.

  15. 始终如一.如果你开始遵循惯例的一条路径,除非你愿意重构以前的所有工作,否则不要中途换马.这应该扼杀任何"不会是伟大的,如果......"的想法,最终导致混乱和大量的返工.

  16. 在打字之前先想想.你真的需要那张桌子,场地,杂物或视图吗?你确定它不在其他地方吗?在添加之前获得一致意见.如果由于某种原因您必须将其取出,请先与您的团队联系.我一直在DBA每天都在不考虑开发人员的情况下做出改变的地方.这不好玩.

  • 非常不同意#10,这是一个非常糟糕的做法大多数时候,你必须改变表结构来添加一个新的手机类型.你会惊讶地发现有些人需要存储多少个电话号码.我非常同意#8. (13认同)
  • #10为+1.你不能夸大过度正常化的代价. (5认同)
  • @Tapori,我同意#10可能在某种程度上取决于系统要求.但是,我不认为你的例子很好.对于通话记录,最好将实际的电话号码放在历史记录表中,与地址相同.它应该在Order表中.原因是,即使有人从"电话"或"地址"表中删除了记录,这也可以保持历史记录的完整性.重复数据?可能,但您的数据更容易报告,并且这些字段中的数据永远不会改变. (2认同)

Ric*_*dOD 7

如果数据库用于特定应用程序,请使用版本表,以便可以根据代码版本(以及其他原因)检查数据库版本.


Sql*_*yan 6

我总是尽量不使用字段名称中的类型 - "sFirstName","sLastName"或"iEmployeeID".虽然它们最初匹配,但如果发生变化,它们将不同步,以后更改这些名称会非常头疼,因为您还必须更改依赖对象.

Intellisense和GUI工具使得找出列的类型变得微不足道,因此我觉得这不是必需的.


Tom*_*ard 5

WITH子句确实有助于将查询分解为可管理的部分.

它还有助于提高查询的执行计划的效率.


Cad*_*oux 5

确保每个varchar/nvarchar选项都是合适的.

确保每个NULLable列选择都是合适的 - 尽可能避免使用NULLable列 - 允许NULL应该是合理的位置.

无论您在此处的建议中使用何种其他规则,我都会在数据库中创建一个可以定期运行的存储过程,以确定您拥有的任何规则或标准的系统运行状况(其中一些是一点SQL) - 特定于服务器):

  • 在任何由于某种原因无法使用DBMS系统的参照完整性的情况下查找孤立记录(在我的系统中,我有一个进程表和一个测试表 - 所以我的system_health SP在没有测试的情况下查找进程,因为我只有一个单向FK关系)

  • 寻找空架构

  • 查找没有主键的表

  • 寻找没有任何索引的表

  • 查找没有文档的数据库对象(我们使用SQL Server扩展属性将文档放在数据库中 - 此文档可以像一样精细).

  • 查找特定于系统的问题 - 需要归档的表,不是正常月度或日常处理的异常,具有或不具有默认值的某些常见列名(比如CreateDate).

  • 寻找非确定性UDF

  • 查找TODO注释以确保数据库中的代码不会以某种方式具有未经测试或预发布的代码.

所有这些都可以自动化,为您提供系统健康状况的整体情况.