大型.NET ERP系统的20条数据库设计规范

数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到。当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考。在程序框架中,也有一份强制性的约定,当不遵守规范时报错误。

以下20个条款是我从一个超过1000个数据库表的大型ERP系统中提炼出来的设计约定,供参考。

1 所有的表的第一个字段是记录编号Recnum,用于数据维护

[Recnum] [decimal] (8, 0) NOT NULL IDENTITY(1, 1)

在进行数据维护的时候,我们可以直接这样写:

UPDATE Company SET Code='FLEX' WHERE Recnum=23

2 每个表增加4个必备字段,用于记录该笔数据的创建时间,创建人,最后修改人,最后修改时间

[CreatedDate] [datetime] NULL,
[CreatedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[RevisedDate] [datetime] NULL,
[RevisedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL

框架程序中会强制读取这几个字段,默认写入值。

3 主从表的主外键设计

主表用参考编号RefNo作为主键,从表用RefNo,EntryNo作为主键。RefNo是字符串类型,可用于单据编码功能中自动填写单据流水号,从表的EntryNo是行号,LineNo是SQL Server 的关键字,所以用EntryNo作为行号。

如果是三层表,则第三层表的主键依次是RefNo,EntryNo,DetailEntryNo,第三个主键用于自动增长行号。

4 设计单据状态字段


字段


含义


Posted


过帐,已确认


Closed


已完成


Cancelled


已取消


Approved


已批核


Issued


已发料


Finished


已完成


Suspended


已取消

5 字段含义相近,把相同的单词调成前缀。

比如工作单中的成本核算,人工成本,机器成本,能源成本,用英文表示为LaborCost,MachineCost,EnergyCost

但是为了方便规组,我们把Cost调到字段的前面,于是上面三个字段命名为CostLabor,CostMachine,CostEnergy。

可读性后者要比前者好一点,Visual Studio或SQL Prompt智能感知也可帮助提高字段输入的准确率。

6 单据引用键命名 SourceRefNo SourceEntryNo

销售送货Shipment会引用到是送哪张销售单据的,可以添加如下引用键SourceRefNo,SourceEntryNo,表示送货单引用的销售单的参考编号和行号。Source开头的字段一般用于单据引用关联。

7 数据字典键设计

比如员工主档界面的员工性别Gender,我的方法是在源代码中用枚举定义。性别枚举定义如下:

public enum Gender
{
[StringValue("M")]
[DisplayText("Male")]
Male,

[StringValue("F")]
[DisplayText("Female")]
Female
}

在代码中调用枚举的通用方法,读取枚举的StringValue写入到数据库中,读取枚举的DisplayText显示在界面中。

经过这一层设计,数据库中有关字典方面的设计就规范起来了,避免了数据字典的项的增减给系统带来的问题。

8 数值类型字段长度设计

Price/Qty 数量/单价 6个小数位 nnnnnnnnnn.nnnnnn 格式 (10.6)

Amount 金额 2个小数位 nnnnnnnnnnnn.nn 格式(12.2)

Total Amt 总金额 2个小数位 nnnnnnnnnnnnnn.nn 格式(14.2)

参考编号默认16个字符长度,不够用的情况下增加到30个字符,再不够用增加到60个字符。这样可以保证每张单据的第一个参考编号输入控件看起来都是一样长度。

除非特别需求,一般而言,界面中控件的长度取自映射的数据库中字段的定义长度。

9 每个单据表头和明细各增加10个自定义字段,基础资料表增加20个自定义字段

参考供应商主档的自定义字段,自定义字段的名称统一用UserDefinedField。

ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_1] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_2] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_3] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_4] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_5] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_6] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_7] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_8] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_9] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_10] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_11] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_12] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_13] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_14] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_15] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_16] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_17] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_18] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_19] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
ALTER TABLE Vendor ADD COLUMN [USER_DEFINED_FIELD_20] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL

10 多货币(本位币)转换字段的设计

金额或单价默认是以日记帐中的货币为记录,当默认货币与本位币不同时需要同时记录下本位币的值。

销售单销售金额 SalesAmount或SalesAmt,本位币字段定义为SalesAmountLocal或SalesAmtLocal

通常是在原来的字段后面加Local表示本位币的值。

11 各种日期字段的设计


字段名称


含义


TranDate


日期帐日期 Tran是Transaction的简写


PostedDate


过帐日期


ClosedDate


完成日期


InvoiceDate


开发票日期


DueDate


截止日期


ScheduleDate


计划日期,这个字段用在不同的单据含义不同。比如销售单是指送货日期,采购单是指收货日期。


OrderDate


订单日期


PayDate


付款日期


CreatedDate


创建日期


RevisedDate


修改日期


SettleDate


付款日期


IssueDate


发出日期


ReceiptDate


收货日期


ExpireDate


过期时间

12 财务有关的单据包含三个标准字段

FiscalYear 财年,PeriodNo 会计期间,Period 前面二个的组合。以国外的财年为例子,FiscalYear是2015,PeriodNo是4,Period是2015/04。

欧美会计期间是从每年的4月份开始,需要注意的是会计期间与时间没有必然的联系,看到会计期间是2015/04,不一定是表示2015的4月份,它只是说这是2015财年的第四期,具体在哪个时间段需要看会计期间定义。

13 单据自动生成 DirectEntry

有些单据是由其它单据生成过来的,逻辑上应该不支持编辑。比如销售送货Shipment单会产生出仓单,出仓单应该不支持编辑,只能做过帐扣减库存

操作。这时需要DirectEntry标准字段来表示。当手工创建一张出仓单时,将DirectEntry设为true,表示可编辑单据中的字段值,当由
其它单据传递产生过来产生的出仓单,将DirectEntry设为false,表示不能编辑此单据。这种情况还发生在业务单据产生记帐凭证
(Voucher)的功能中,如果可以修改由原始单据传递过来的数量金额等字段,则会导致与源单不匹配,给系统对帐产生困扰。

14 百分比值字段的设计

Percentage百分比值,用于折扣率,损耗率等相关比率设定的地方。推荐用数值类型表示,用脚本表示是

[ScrapRate] [decimal] (5, 2) NULL

预留两位小数,整数部分支持1-999三位数。常常是整数部分2位就可以,用3位也是为了支持一些特殊行业(物料损耗率超过100)的要求。

15 日志表记录编号LogNo字段设计

LogNo字段的设计有些巧妙,以出仓单为例子,一张出仓单有5行物料明细,每一行物料出仓都会扣减库存,再写物料进出日记帐,因为这五行物料出仓

来自同一个出仓单,于是将这五行物料的日记帐中的LogNo都设为同一个值。于在查询数据时,以这个字段分组即可看到哪些物料是在同一个时间点上出仓的,
对快速查询有很重要的作用。

16 基础资料表增加名称,名称长写,代用名称三个字段

比如供应商Vendor表,给它加以下三个字段:

Description 供应商名称,比如微软公司。

ExtDescription 供应商名称长写,比如电气行业的南网的全名是南方国家电网有限公司。

AltDescription 供应商名称替代名称,用在报表或是其它单据引用中。比如采购单中的供应商是用微软,还是用代用名称Microsoft,由参数(是否用代用名称)控制。

17 文件类表增加MD5 Hash字段

比如产品数据管理系统要读取图纸,单据功能中增加的附件文件,这类涉及文件读写引用的地方,考虑存放文件的MD5哈希值。文件的MD5相当于文件的

唯一识别身份,在网上下载文件时,网站常常会放出文件的MD5值,以方便对比核对。当下载到本机的文件的MD5值与网站上给出的值不一致时,有可能这个文
件被第三方程序修改过,不可信任。

18 数据表的主键用字符串而不是数字

比如销售单中的货币字段,是存放货币表的货币字符串值RMB/HKD/USD,还是存放货币表的数字键,1/2/3。

存放前者对于报表制作相对容易,但是修改起来相对麻烦。存放后者对修改数据容易,但对报表类或查询类操作都需要增加一个左右连接来看数字代表的货币。金蝶使用的是后者,它的BOS系统也不允许数据表之间有直接的关联,而是间接通过Id值来关联表。

在我看到的系统中,只有一个会计期间功能(财年Fiscal Year)用到数字值作主键,其余的单据全部是字符串做主键。

19 使用约定俗成的简写

模块Module 简写


简写


全名


SL


Sales 销售


PU


Purchasing 采购


IC


Inventory 仓库


AR


Account Receivable 应收


AP


Account Payable 应付


GL


General Ledger 总帐


PR


Production 生产

名称Name 简写


简写


全名


Uom


Unit of Measure 单位


Ccy


Currency 货币


Amt


Amount 金额


Qty


Quantity 数量


Qty Per


Quantity Per 用量


Std Output


Standard Output 标准产量


ETA


Estimated Time of Arrival 预定到达时间


ETD


Estimated Time of Departure 预定出发时间


COD


Cash On Delivery 货到付款


SO


Sales Order 销售单


PO


Purchase Order 采购单

20 库存单据数量状态

Qty On Hand 在手量

Qty Available 可用量

Qty On Inspect 在验数量

Qty On Commited 提交数量

Qty Reserved 预留数量

以上每个字段都有标准和行业约定的含义,不可随意修改取数方法。

来源:51CTO

时间: 2024-09-13 21:03:06

大型.NET ERP系统的20条数据库设计规范的相关文章

解析大型.NET ERP系统 20条数据库设计规范

数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到.当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考.在程序框架中,也有一份强制性的约定,当不遵守规范时报错误. 以下20个条款是我从一个超过1000个数据库表的大型ERP系统中提炼出来的设计约定,供参考. 1  所有的表的第一个字段是记录编号Recnum,用于数据维护 [Recnum] [decimal] (8, 0) NOT NULL IDENTITY(1, 1) 在进行数据维护的时候,我们可以直接这

解析大型.NET ERP系统 代码的坏味道

1  对用户输入做过多的约定和假设 配置文件App.config中有一个设定报表路径的配置节: <add key="ReportPath" value="C:\Users\Administrator"/> 在程序中有一个销售报表文件SalesReport.rpt,用代码调用这个报表,可能会写成: string salesReport=ReportPath + "SalesReport.rpt"; 因为路径末尾没有加反斜线,会抛出找不到

大型.net ERP高质量代码设计模式及数据库设计规范

大型.NET ERP系统高质量代码设计模式 1 缓存 Cache 系统中大量的用到缓存设计模式,对系统登入之后不变的数据进行缓存,不从数据库中直接读取.耗费一些内存,相比从SQL Server中再次读取数据要划算得多.缓存的基本设计模式参考下面代码: private static ConcurrentDictionary<string, LookupDialogEntity> _cachedLookupDialogEntities = new ConcurrentDictionary<s

简单了解一下什么是ERP系统数据库

一个典型的http://www.aliyun.com/zixun/aggregation/29 808.html">ERP系统是有一组基于共享数据库的应用程序所组成的.可见,数据库是各应用模块间沟通的桥梁和纽带.比如,对预测模块.定单录入模块以及计划模块来说,每个模块都可以独立地做出决策,输出某些指导性的结果.当定单通过定单录入模块的界面录入以后,系统会自动通过计划模块生成一个交付日期,然而这个日期只是根据生产能力.已排产计划等数据来生成的,未必能令客户满意.一旦客户对这个交付日期有异议,

算法,PHP取数据库中百万条数据中随机20条记录

额,为什么要写这个? 在去某个公司面试时,让写个算法出来,当时就蒙了,我开发过程中用到算法的吗?又不是大数据开发,分析. 今天偶然想起来一个坑爹数据,如:PHP取百万条数据中随机20条记录,当时就用的算法. 1.先统计统计数据库多少条记录(这个做个数据缓存,如1小时重新统计一次), 2.根据总条数,随机1次,1次性取出20条记录(当然这个就相当于分页了,要求不高的话,这个最快,我用的就是这个): 还有一种方法,随机20次,重复执行20次. 例如: $sum=800000;//得到总条数 //循环

《Effective Debugging:软件和系统调试的66个有效方法》——第20条:开始调试之前与调试完毕之后都要把程序清理干净

第20条:开始调试之前与调试完毕之后都要把程序清理干净 如果你要调试的软件有10个地方可能出错,那么这些错误就会有上千种(2的10次方)表现形式,如果有20个地方可能出错,那么表现形式就会高达一百多万种(2的20次方).因此,在调试的时候,应该优先关注当前区域中最容易解决的那些问题.例如: 能够借助工具而找到的问题(参见第51条). 程序在运行时所产生的警告(例如,可恢复的断言失败). 读起来比较费解,而且与你要调试的bug有所关联的那些代码(参见第48条). 标有XXX.FIXME及TODO字

ERP系统之比较——SAP、Oracle、BAAN、JDE、SSA

ERP系统之比较--SAP.Oracle.BAAN.JDE.SSA   ERP/MRPII系统剖析SAP SAP公司简介R/2和R/3系统是德国SAP公司所提供的MRPII产品.R/2是用于集中式大型机环境的系统,R/3是用于分布式的客户机/服务器环境的系统.SAP是国际上著名的标准应用软件公司.SAP总部设在德国南部的沃尔道夫市,公司成立于1972年,1988年成为德国股票上市公司.到1995年底,SAP在世界40多个国家和地区设有代表处和独立子公 司,具有近5000家用户,成为世界第五大软件

ERP系统BETA测试攻略

关于ERP,关于BETA测试理论性的文章太多了,看多了就是两种结果,经历过的只当看过了,没经历过的还是不知道怎么做.最近产品要发版了,准备开展BETA测试,10余家的BETA测试项目,无奈新人太多,怎么才能让大家了解到BETA测试的实战经验以及遇到困难的时候如何应对?今天加班"愤笔急书"写了一个BETA测试攻略,在这里也拿来和大家分享一下,希望我的经验能够成为你开展BETA测试的锦囊妙计.文章中没有太多讲解BETA测试的理论,如果你还不明白的,可以先看一下BETA测试相关的理论知识,同

如何做好ERP系统选型工作

众所周知,ERP项目前期筹备工作--软件选型的正确性和前期相关准备工作是否充分是整个ERP项目能否取得成功的重要前提之一. 如何选择适合于本企业管理需求的ERP系统和选择提供实施咨询的管理顾问公司是实施ERP项目的企业首先要解决的,本文从前期筹备工作步骤.侧重点.选择软件及顾问咨询公司的方法以及洽谈实施合同的关键点等方面分别论述. 在项目前期筹备工作中,我们主要开展了如下方面的工作,经事后总结,我认为这些都是ERP项目正确选型必不可少的重要工作: 1.组建ERP项目筹备组及策划筹备工作项 2.对