使用数据库

  • 建表时不应使用数据库内置关键字,否则会造成许多隐藏的问题;
  • 表数据进行关联时选用和业务无关的字段进行关联,比如现在我们经常使用与业务无关的字段作为 id,关联时也使用该字段;
  • 真正的 ORM 框架更加重视建模的规范,前期的建模一旦做好,在业务开发和后期中将无往不利,所以 ORM 的选择是重中之重,对项目的影响是很大的(前提是使用数据库存储);
  • 关系型数据库分 database.schema.table,一个数据库可以有多个 schema,一个 schema 下可以有多个数据库对象,比如表、存储过程、触发器等(MySQL 的 Schema 和 Database 是等价的);
  • 国内使用 MyBatis/MP 的公司数据库建模有待加强;根据业务场景合理使用外键可以构建更健壮的系统;

什么是业务无关?

以订单表为例,一般都有唯一的订单号,但是我们实际使用中还是使用订单表的 id 与其他表关联,而不是使用订单号,因为它具有业务意义。

数据库三范式

数据库三范式是关系型数据库设计的基础理论,用来保证数据的完整性和减少数据冗余。三范式层层递进,每个范式都是在前一个范式的基础上进行优化和改进。在实际的数据库设计中,应根据具体的需求和场景选择合适的范式来保证数据的完整性和减少数据冗余。

  1. 第一范式(1NF):它要求每个属性都必须原子性,也就是不可再分。这个范式的目的是确保数据的完整性,防止数据被不合理地分解 (分到不可再分,一个字段只代表一个含义)
  2. 第二范式(2NF):第二范式要求在满足第一范式的前提下,非主键属性必须完全依赖于主键,而不是部分依赖 (按照属性进行归类并拆分表进行关联)
  3. 第三范式(3NF):在满足第一、二范式的前提下,非主键属性之间不能存在依赖关系。也就是说,每个属性必须是独立的,不能依赖于其他属性 (高度可维护)

实现了三范式,基本上就是 一张表维护一种数据,然后使用主键进行关联合并为一个整体。

数据字典的必要性

我们经常有类似这样的场景:有合同信息,合同信息中有合同类型;有车辆信息,车辆信息中有车辆类型;有人员信息,人员信息中有人员类型…

这种情况,我们有两种一般的做法:

  1. 单独建立类型表,但是他们的结构差不多,并且这种类似的场景有很多的话就要多出许多类型表;
  2. 使用数据库字典;

使用数据字典的话就可以避免建立过多的类型表,后续维护的话也只用修改数据字典表就可以,否则可能这些类型不仅要建表,还要单独开发一些类型页进行管理,无疑增加了工作量,用户维护的时候也很繁琐,需要点击多个不同的类型管理页面进行。

数据字典的建立一般分为以下几种:

  1. 一张表,简单的 name、value;
  2. 一张表,在 name、value 之上添加 dict_type、dict_name
  3. 两张表,dict_type、dict_name 一张表,name、value、dict_type 一张表(若依开源框架就是使用的这种)

就目前的开发而言,第三种方式更加的常见,这样可以适用于不同的场景,并且可以充分的利用数据字典表,对于维护也是很好的,无非就是效率相较而言慢一些,这个影响不大,我们有缓存。

数据字典类型表(dict_type):

字段名称 含义 示例值
dict_type 字典分类 GENDER
dict_name 字典分类说明/标签 性别

数据字典数据表(dict_data):

字段名称 含义 示例值
dict_type 字典分类 GENDER
name 字典标签
value 字典值 MAIL

因此,现在的数据字典一般都是这样设计,不仅适用于敏捷开发,更利于使用和维护。当然,我们也能立马就看出来,有父子关系的树状结构不适用于该方式,所以那种类型表还是需要单独建立的。

JDBC URL 参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# db2 示例:jdbc:db2://localhost:50000/MYDB:user=dbadm;password=dbadm;
# https://www.ibm.com/support/knowledgecenter/SSEPGG_11.5.0/com.ibm.db2.luw.apdv.java.doc/src/tpc/imjcc_r0052342.html
jdbc:db2://<serverName>[:<portNumber>]/<databaseName>[:<key1>=<value>;[<key2>=<value2>;]]

# h2 示例:jdbc:h2:tcp://localhost/~/test,jdbc:h2:mem:myDB
# https://h2database.com/html/features.html#database_url
jdbc:h2:{ {.|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value…​]

# mariadb 示例:jdbc:mariadb://localhost:3306/test
jdbc:mariadb:[replication:|failover:|sequential:|aurora:]//<hostDescription>[,<hostDescription>…​]/[database][?<key1>=<value1>[&<key2>=<value2>]] hostDescription:: <host>[:<portnumber>] or address=(host=<host>)[(port=<portnumber>)][(type=(master|slave))]

# mssql 示例:jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks
# https://docs.microsoft.com/en-us/sql/connect/jdbc/connecting-to-sql-server-with-the-jdbc-driver?view=sql-server-2017
jdbc:sqlserver://[serverName[\instanceName][:portNumber]][;property=value[;property=value]]

# oracle 示例:jdbc:oracle:thin:@localhost:1521/ORCL_SVC
# https://docs.oracle.com/en/database/oracle/oracle-database/21/jjdbc/data-sources-and-URLs.html#GUID-AEA8E228-1B21-4111-AF4C-B1F33744CA08
jdbc:oracle:driver_type:@database_specifier

# pg 示例:jdbc:postgresql://localhost:5432/test
# https://jdbc.postgresql.org/documentation/head/connect.html
jdbc:postgresql:[//][host][:port][/database][?key=value…​]

SQL

Oracle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 补全一年 12 个月
select lpad(level,2,0) from dual connect by level<13

select to_char(sysdate, 'yyyy-') || lpad(level, 2, 0) datevalue from dual connect by level < 13;

--oracle 未来12个月
SELECT TO_CHAR(ADD_MONTHS(ADD_MONTHS(SYSDATE, 0), ROWNUM - 1), 'YYYY-MM') AS YEARMONTH
FROM ALL_OBJECTS
WHERE ROWNUM <= 12;

--oracle 前12个月
SELECT TO_CHAR(ADD_MONTHS(SYSDATE, 1 - ROWNUM), 'YYYY-MM') AS YEARMONTH
FROM ALL_OBJECTS
WHERE ROWNUM <= 12;

hive、oracle、mysql内建函数对照表


本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。