JavaRush /Java 博客 /Random-ZH /第 2 部分:DBMS 结构、表和数据类型
Marat Sadykov
第 41 级

第 2 部分:DBMS 结构、表和数据类型

已在 Random-ZH 群组中发布
第一部分
第 2 部分. DBMS 结构、表和数据类型 - 1
我们继续创建简单的证券交易所模拟器。这是我们要做的:
  • 让我们创建一个数据库组织图。
  • 我们将描述它存储的内容、方式和位置。
  • 让我们看看数据是如何相互关联的。
  • 让我们以 SQL 表创建命令CREATE TABLE(SQL 语言的数据定义语言 ( DDL ))为例开始学习 SQL 的基础知识 。
  • 让我们继续编写Java程序。我们使用 JDBC 和三层架构以编程方式创建数据库的 java.sql 来实现 DBMS 的主要功能。
这两部分内容更加冗长,因为我们需要从内部熟悉 SQL 的基础知识和 DBMS 的组织,并与 Java 进行类比。为了不让代码清单让您感到厌烦,最后有该程序对应的提交 github 存储库的链接。

数据库管理系统设计

应用说明

您已经听说组织数据存储是编程的一个组成部分。让我提醒您,我们应用程序的目的是最简单的交换模拟:
  • 股票的价值在交易日内可以按照规定的规则发生变化;
  • 有初始资金的交易者;
  • 交易者可以根据他们的算法买卖股票。
交易所以固定时间段(在我们的例子中为 1 分钟)运行。在价格变动期间,股票价格可能会发生变化,然后交易者可以买入或卖出股票。

交换仿真数据结构

我们将其称为单独的交换实体模型。为了避免舍入错误,我们将通过一个类来处理财务金额BigDecimal(详细信息可以在文章末尾的链接中找到)。让我们更详细地描述每个模型的结构: 促销:
属性 类型 描述
name 斯丁 姓名
changeProbability 整数 每个价格变动的利率变化概率(百分比)
startPrice 大十进制 初始投资成本
delta 整数 当前值可以更改的最大百分比量
分享价格:
属性 类型 描述
operDate 本地日期时间 设置费率的时间(tick)
share 晋升 促销链接
rate 大十进制 分享价格
商人:
属性 类型 描述
name 细绳 设置费率的时间(tick)
sfreqTick 整数 交易频率。由交易者执行操作之前的时间段(以跳动点为单位)指定
cash 大十进制 除股票以外的金额
traidingMethod 整数 交易者使用的算法。让我们将其设置为一个常数,算法的实现将在Java代码中(在下面的部分中)
changeProbability 整数 完成操作的概率,百分比
about 细绳 每个价格变动的利率变化概率(以百分比表示)
交易者行动:
属性 类型 描述
operation 整数 交易类型(买入或卖出)
traider 商人 交易者链接
shareRate 分享价格 与股票价格的链接(分别是股票本身、其利率和发行时间)
amount 长的 本次交易涉及的股份数量
为了确保每个模型的唯一性,我们将添加一个longid类型的属性。该属性在模型实例中是唯一的,并且可以唯一地标识它。引用其他模型(交易者、股票、股票价格)的属性可以使用此属性来唯一标识相应的模型。我立刻想到我们可以用来 存储这样的数据,相应的模型在哪里。但是,请尝试在以下条件下在代码中实现此功能: idMap<Long, Object>Object
  • 数据大小明显超过可用 RAM 的大小;
  • 预计可以从十几个不同的地方访问数据;
  • 需要同时修改和读取数据的能力;
  • 有必要确保数据的形成和完整性规则;
...您将面临需要适当资格和时间来实施的任务。没有必要“重新发明轮子”。很多事情已经为我们想好了并写好了。所以我们将使用多年来已经测试过的东西。

在 Java 中存储数据

让我们考虑一下行动。在 Java 中,我们为此模型创建了一个特定的类,Share其中包含字段name, changeProbability, startPrice, delta。许多共享存储为Map<Long, Share>,其中密钥是每个共享的唯一标识符。
public class Share {
    private String name;
    private BigDecimal startPrice;
    private int changeProbability;
    private int delta;
}
Map<Long, Share> shares = new HashMap<>();
shares.put(1L, new Share("ibm", BigDecimal.valueOf(20.0), 15, 10));
shares.put(2L, new Share("apple", BigDecimal.valueOf(14.0), 25, 15));
shares.put(3L, new Share("google", BigDecimal.valueOf(12.0), 20, 8));
...
shares.put(50L, new Share("microsoft", BigDecimal.valueOf(17.5), 10,4 ));
要通过 ID 访问所需的促销活动,请使用方法shares.get(id)。对于按名称或价格查找股票的任务,我们将循环遍历所有记录以查找我们需要的记录,依此类推。但我们会采取相反的方式,将值存储在 DBMS 中。

DBMS 中的数据存储

让我们为 DBMS 制定一组初始的数据存储规则:
  • DBMS 中的数据被组织成表 ( TABLE ),表是一组记录。
  • 所有记录都具有相同的字段集。它们是在创建表时设置的。
  • 该字段可以设置为默认值 ( DEFAULT )。
  • 对于表,您可以设置约束 ( CONSTRAINT ) 来描述其数据的要求,以确保其完整性。这可以在表创建阶段( CREATE TABLE )完成或稍后添加(ALTER TABLE ... ADD CONSTRAINT)。
  • 最常见的约束
    • 主键是 PRIMARY (在我们的例子中是 Id )。
    • 唯一值字段UNIQUE(车辆表的VIN)。
    • 检查CHECK字段(百分比值不能大于100)。字段的私有限制之一是NOT NULLNULL,它禁止/允许在表字段中存储 NULL。
    • 链接到第三方表FOREIGN KEY(链接到股价表中的股票)。
    • 索引INDEX(对字段建立索引以加快在其中搜索值的速度)。
    • 如果记录的字段值与限制(CONSTRAINT)相矛盾,则不会发生记录的修改( INSERTUPDATE )。
  • 每个表可以有一个(或多个)关键字段,可用于唯一标识一条记录。这样的字段(或多个字段,如果它们形成组合键)形成表的主键 - PRIMARY KEY
    • 主键保证了表中记录的唯一性;在主键上创建索引,可以根据键值快速访问整个记录。
    • 拥有主键可以更轻松地在表之间创建链接。接下来,我们将使用人工主键:对于第一条记录id = 1,后续的每条记录都将插入到表中,并且 id 值加一。此键通常称为AutoIncrementAutoIdentity
实际上是一个股票表: 第 2 部分. DBMS 结构、表和数据类型 - 2 在这种情况下是否可以使用股票名称作为键?总的来说 - 是的,但有可能某些公司发行不同的股票并仅以自己的名称命名。在这种情况下,将不再有唯一性。在实践中,经常使用人工主键。同意,在包含人员记录的表中使用全名作为唯一键并不能确保唯一性。以及使用全名和出生日期的组合。

DBMS 中的数据类型

与任何其他编程语言一样,SQL 也具有数据类型。以下是最常见的 SQL 数据类型: 整数类型
SQL类型 SQL 同义词 Java中的匹配 描述
INT INT4,整数 java.lang.Integer 4 字节整数,-2147483648 … 2147483647
布尔值 布尔、位 java.lang.布尔值 真假
天音 java.lang.Byte 1 字节整数,-128 … 127
小智 INT2 java.lang.Short 2 字节整数,-32768 … 32767
BIGINT INT8 java.lang.Long 8 字节整数,-9223372036854775808 … 9223372036854775807
自动递增 增量 java.lang.Long 表独有的增量计数器。如果插入一个新值,它就会加一,生成的值永远不会重复。
真实的
SQL类型 SQL 同义词 Java中的匹配 描述
小数(N,M) 十二月,数字 java.math.BigDecimal 固定精度小数(N 个整数位和 M 个小数位)。主要设计用于处理财务数据。
双倍的 浮点8 java.lang.Double 双精度实数(8 字节)。
真实的 浮点数4 java.lang.Real 单精度实数(4 字节)。
细绳
SQL类型 SQL 同义词 Java中的匹配 描述
VARCHAR(N) NVARCHAR java.lang.String 长度为 N 的 UNICODE 字符串。长度限制为 2147483647 将字符串的全部内容加载到内存中。
日期和时间
SQL类型 SQL 同义词 Java中的匹配 描述
时间 java.time.LocalTime、java.sql.Time 存储时间(最多纳秒),转换为DATETIME时,日期设置为1970年1月1日。
日期 java.time.LocalDate、java.sql.Timestamp 以 yyyy-mm-dd 格式存储日期,时间设置为 00:00
约会时间 时间戳 java.time.LocalDateTime、java.sql.Timestamp 存储日期+时间(不考虑时区)。
大量数据的存储
SQL类型 Java中的匹配 描述
BLOB java.io.InputStream、java.sql.Blob 存储二进制数据(图片、文件...)。
CLOB java.io.Reader、java.sql.Clob 与 VARCHAR 不同,存储大型文本数据(书籍、文章...)是将数据分部分加载到内存中。

SQL 编写风格

对于许多语言,都有代码格式指南。通常,此类文档包含变量、常量、方法和其他语言结构的命名规则。因此,对于 Python,有 PEP8,对于Java - Oracle Code Conventions for Java。已经为 SQL 创建了几个不同的集,它们之间略有不同。无论如何,您应该养成在格式化代码时遵循规则的习惯,尤其是在团队中工作时。例如,规则可以是以下(当然,您可以为自己制定一套不同的规则,主要是将来坚持它们):
  • 关键字和保留字,包括命令和运算符,必​​须用大写字母书写:CREATE TABLE、CONSTRAINT...
  • 表、字段和其他对象的名称不应与 SQL 语言关键字重合(请参阅文章末尾的链接),但可以包含它们。
  • 表名称应反映其用途。它们以小写字母书写。名称中的单词之间用下划线分隔。末尾的单词必须是复数:traders(交易者)、share_rates(份额率)。
  • 表字段名称应反​​映其用途。它们必须以小写字母书写,名称中的单词必须采用驼峰式格式,并且末尾的单词必须使用单数:name(名称)、share_rates(分享率)。
  • 人工关键字段必须包含单词 id。
  • CONSTRAINT 名称必须遵循表命名约定。它们还必须包括其中涉及的字段和表,以语义前缀开头:check_(检查字段值)、pk_(主键)、fk_(外键)、uniq_(字段唯一性)、idx_(索引)。示例:pk_traider_share_actions_id(trader_share_actions 表的 id 字段上的主键)。
  • 依此类推,当你学习 SQL 时,规则列表将会被补充/更改。

数据库管理系统设计

在创建 DBMS 之前,需要对其进行设计。最终模式包含表、一组字段、约束、键、字段的默认条件、表和其他数据库实体之间的关系。在 Internet 上,您可以找到许多免费的在线/离线设计器来设计小型 DBMS。尝试在搜索引擎中输入“免费数据库设计器”之类的内容。此类应用程序具有有用的附加属性:
  • 可以生成SQL命令来创建DBMS。
  • 在图表上直观地显示设置。
  • 允许您移动表格以获得更好的可视化效果。
  • 在图表上显示键、索引、关系、默认值等。
  • 他们可以远程存储 DBMS 模式。
例如,dbdiffo.com突出显示键、显示非空字段和带有 NN 标签的 AI(自动增量)计数器:
第 2 部分. DBMS 结构、表和数据类型 - 3

在 DBMS 中创建表

所以我们有一个图表。现在让我们继续创建表 (CREATE TABLE)。为此,我们建议获得初步数据:
  • 表名
  • 字段名称和类型
  • 字段的限制(CONSTRAINTS)
  • 字段的默认值(如果可用)
  • 主键 (PRIMARY KEY) 如果可用
  • 表之间的连接(外键)
我们不会详细研究 CREATE TABLE 命令的所有选项;我们将使用为交易者创建表的示例来了解 SQL 基础知识:
CREATE TABLE traiders(
	id BIGINT AUTO_INCREMENT PRIMARY KEY,
	name VARCHAR(255) NOT NULL,
	freqTiсk INTEGER NOT NULL,
	cash  DECIMAL(15,2) NOT NULL DEFAULT 1000,
	tradingMethod INTEGER NOT NULL,
	changeProbability INTEGER NOT NULL DEFAULT 50,
	about VARCHAR(255) NULL
);
ALTER TABLE traiders ADD CONSTRAINT check_traiders_tradingMethod
	CHECK(tradingMethod IN (1,2,3));
ALTER TABLE traiders ADD CONSTRAINT check_traiders_changeProbability
	CHECK(changeProbability <= 100 AND changeProbability > 0)
让我们仔细看看:
  • CREATE TABLE traiders(字段描述)- 创建具有指定名称的表;在描述中,字段以逗号分隔。任何命令都以分号结尾。
  • 字段描述以其名称开头,后跟其类型、CONSTRAINT 和默认值。
  • id BIGINT AUTO_INCREMENT PRIMARY KEY– 整数类型的 id 字段是一个主键和一个增量计数器(对于 id 字段的每条新记录,都会生成一个值,该值比该表之前创建的值大 1)。
  • cash DECIMAL(15,2) NOT NULL DEFAULT 1000– 现金字段,小数,小数点前 15 位,小数点后两位(财务数据,例如美元和美分)。不能接受 NULL 值。如果没有给定值,它将获得值 1000。
  • about VARCHAR(255) NULL– about 字段,一个最长 255 个字符的字符串,可以接受空值。
注意,我们可以在建表后设置部分CONSTRAINT条件。让我们考虑一下修改表结构及其字段的构造: ALTER TABLE table_name ADD CONSTRAINT constrain_name CHECK (condition)使用示例:
  • CHECK(tradingMethod IN (1,2,3))– TradingMethod字段只能取值1,2,3
  • CHECK(changeProbability <= 100 AND changeProbability > 0)–changeProbability字段可以取1到100范围内的整数值

表之间的关系

为了分析表之间关系的描述,我们看一下share_rates的创建:
CREATE TABLE share_rates(
	id BIGINT AUTO_INCREMENT PRIMARY KEY,
	operDate datetime NOT NULL,
	share BIGINT NOT NULL,
	rate DECIMAL(15,2) NOT NULL
);
ALTER TABLE share_rates ADD FOREIGN KEY (share) REFERENCES shares(id)
第 2 部分. DBMS 结构、表和数据类型 - 4
可以按如下方式设置到另一个表的值的链接: ALTER TABLEtable_from_which_is_referred ADD FOREIGN KEY(field_which_referred) REFERENCEStable_to_which_is_referenced (field_which_is_referenced) 让我们有关于股票的记录,例如,对于 id=50,我们存储初始价格为 17.5 的 Microsoft 股票,增量为 20,变化机会为 4%。对于share_rates表,我们得到三个主要属性:
  • 我们只需将shares表中的id键的值存储在share字段中,以便使用它从shares表中获取其余信息(名称等)。
  • 我们无法为不存在的促销活动制定费率。您不能在 share 字段中插入不存在的值(shares 表中没有具有此 id 的记录),因为表之间不会存在对应关系。
  • 我们无法删除在 share_rates 中设置费率的股票中的股票条目。
最后两点用于确保存储数据的完整性。您可以使用本文末尾的 github 存储库链接来查看我们模拟的 SQL 表的创建以及相应类方法的 Java 实现中的 SQL 查询示例。 第三部分
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION