MySQL - DECIMAL 十进制数据类型
MySQL 十进制数据类型
MySQL DECIMAL 数据类型用于存储带有小数点的数值。它允许进行精确计算,并且可以配置为在小数点前后存储指定位数。
我们经常将此数据类型用于需要精确精度的列,例如员工工资、员工公积金余额等。
在内部,MySQL 使用二进制格式存储 DECIMAL 值,该格式会分别分配数字的整数部分和小数部分的空间。这种二进制格式可以有效地将 9 位数字打包到 4 个字节的存储空间中。
语法
以下是定义数据类型为 DECIMAL 的列的语法 -
column_name DECIMAL(P,D);
其中:
P 称为精度,它指定了该列中可以存储的有效数字总数,包括小数点左右两边。P 的范围是 1 到 65。
D 是一个标度,它指定了小数点后可以存储的最大位数。 D 的范围应介于 0 到 30 之间,并且 D 小于或等于 (<=) P。
例如,如果我们将一列定义为 DECIMAL(10,2),它可以存储最多 10 位数字,小数点右侧最多 2 位数字。
在 MySQL 中,除了 DECIMAL 关键字,我们还可以使用"DEC"、"FIXED"和"NUMERIC"关键字,因为它们是 DECIMAL 的同义词。
属性
DECIMAL 关键字有两个属性:UNSIGNED 和 ZEROFILL。
UNSIGNED − 使用时,表示该列不接受负数值。
ZEROFILL − 如果使用,它会用零填充数字,直到达到指定的宽度。
精度和小数位数
在下面的查询中,我们定义了一个 DECIMAL 数据类型的 SALARY 列,指定精度为 5,小数位数为 3 −
SALARY decimal(5,3)
此定义表示 SALARY 列最多可以存储 5 位数字的值,包括小数点右侧的 3 位数字。此列的范围为 99.999 至 -99.999。
无小数位
此处,SALARY 列不包含小数部分或小数点。以下两个查询相同 -
SALARY DECIMAL(5); SALARY DECIMAL(5,0);
这两个声明都表明 SALARY 列可以存储整数值,不包含小数位。
默认精度
如果省略精度值,则默认精度 P 为 10 -
SALARY DECIMAL;
MySQL DECIMAL 存储
MySQL 使用二进制格式存储"DECIMAL"数据类型的值,以优化存储。具体来说,MySQL 将 9 位数字打包成 4 个字节。整数部分和小数部分分别分配存储空间,每组 9 位数字占用 4 个字节。剩余数字需要额外的存储空间。
剩余数字所需的存储空间如下表所示:
Leftover Digits | Bytes |
---|---|
0 | 0 |
1-2 | 1 |
3-4 | 2 |
5-6 | 3 |
7-9 | 4 |
假设 DECIMAL(30,9) 列的小数部分有 9 位数字,整数部分有 30 - 9 = 21 位数字。在这种情况下,小数部分占用 4 个字节。整数部分的前 18 位数字占用 8 个字节,剩下的 3 位数字则需要额外的 2 个字节。因此,DECIMAL(30,9) 列总共需要 14 个字节。
示例
为了进一步理解这一点,我们使用以下查询创建一个名为 EMPLOYEES 的表 -
CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) );
使用以下查询,我们将一些记录插入到上面创建的表中 -
INSERT INTO EMPLOYEES (NAME, SALARY) VALUES ("Krishna", 150050.34), ("Kalyan", 100000.65);
得到的 EMPLOYEES 表如下 -
ID | NAME | SALARY |
---|---|---|
1 | Krishna | 150050.3400 |
2 | Kalyan | 100000.6500 |
使用以下查询,我们将 ZEROFILL 属性添加到"SALARY"列中 -
ALTER TABLE EMPLOYEES MODIFY SALARY decimal(14, 4) zerofill;
以下是上述查询的输出 -
Query OK, 2 rows affected, 1 warning (0.03 sec) Records: 2 Duplicates: 0 Warnings: 1
此处,我们尝试在 SALARY 列中添加 ZEROFILL 属性后,从 EMPLOYEES 表中获取所有记录 -
SELECT * FROM EMPLOYEES;
记录将根据"SALARY"列中指定的范围填充零 -
ID | NAME | SALARY |
---|---|---|
1 | Krishna | 0000150050.3400 |
2 | Kalyan | 0000100000.6500 |
使用客户端程序的十进制数据类型
我们也可以使用客户端程序创建十进制数据类型的列。
语法
要通过 PHP 程序创建十进制数据类型的列,我们需要使用 mysqli 函数 query() 执行"CREATE TABLE"语句,如下所示 -
$sql = 'CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) )'; $mysqli->query($sql);
要通过 JavaScript 程序创建十进制数据类型的列,我们需要使用 mysql2 库的 query() 函数执行"CREATE TABLE"语句,如下所示 -
sql = "CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) )"; con.query(sql);
要通过 Java 程序创建十进制数据类型的列,我们需要使用 JDBC 函数 execute() 执行"CREATE TABLE"语句,如下所示 -
String sql = "CREATE TABLE STUDENTS (ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, BRANCH ENUM (\"CSE\", \"ECE\", \"MECH\"), FEES int NOT NULL, PRIMARY KEY (ID))"; statement.execute(sql);
要通过 Python 程序创建十进制数据类型的列,我们需要使用 MySQL Connector/Python 的 execute() 函数执行"CREATE TABLE"语句,如下所示 -
sql = 'CREATE TABLE EMPLOYEES (ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID))' cursorObj.execute(sql)
示例
以下是程序 -
$dbhost = 'localhost'; $dbuser = 'root'; $dbpass = 'password'; $dbname = 'TUTORIALS'; $mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname); if ($mysqli->connect_errno) { printf("Connect failed: %s
", $mysqli->connect_error); exit(); } //printf('Connected successfully.
'); //创建具有布尔列的表 $sql = 'CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) )'; $result = $mysqli->query($sql); if ($result) { printf("Table created successfully...! "); } //将数据插入到创建的表中 $q = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES ('Krishna', 150050.34), ('Kalyan', 100000.65)"; if ($res = $mysqli->query($q)) { printf("Data inserted successfully...! "); } //现在显示表记录 $s = "SELECT ID, Salary FROM EMPLOYEES"; if ($r = $mysqli->query($s)) { printf("Table Records: Where Salary is decimal type! "); while ($row = $r->fetch_assoc()) { printf(" ID: %d, Salary: %s", $row["ID"], $row["Salary"]); printf(" "); } } else { printf('Failed'); } $mysqli->close();
输出
获得的输出如下 -
Table created successfully...! Data inserted successfully...! Table Records: Where Salary is decimal type! ID: 1, Salary: 150050.3400 ID: 2, Salary: 100000.6500
var mysql = require("mysql2"); var con = mysql.createConnection({ host: "localhost", user: "root", password: "password", }); //连接到 MySQL con.connect(function (err) { if (err) throw err; // console.log("Connected successfully...!"); // console.log("--------------------------"); sql = "USE TUTORIALS"; con.query(sql); //创建一个 EMPLOYEES 员工表,接受一列十进制类型。 sql = "CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) )"; con.query(sql); //将数据插入到创建的表中 sql = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES ('Krishna', 150050.34), ('Kalyan', 100000.65)"; con.query(sql); //选择工资的数据类型 sql = `SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'EMPLOYEES' AND COLUMN_NAME = 'SALARY'`; con.query(sql, function (err, result) { if (err) throw err; console.log(result); }); });
输出
生成的输出如下 -
[ { DATA_TYPE: 'decimal' } ]
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class Decimal { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/TUTORIALS"; String username = "root"; String password = "password"; try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); System.out.println("Connected successfully...!"); //Decimal data types...!; String sql = "CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID))"; statement.execute(sql); System.out.println("column of a Decimal type created successfully...!"); ResultSet resultSet = statement.executeQuery("DESCRIBE EMPLOYEES"); while (resultSet.next()){ System.out.println(resultSet.getString(1)+" "+resultSet.getString(2)); } connection.close(); } catch (Exception e) { System.out.println(e); } } }
输出
获得的输出如下所示 -
Connected successfully...! column of a Decimal type created successfully...! ID int NAME varchar(30) SALARY decimal(14,4)
import mysql.connector # 建立连接 connection = mysql.connector.connect( host='localhost', user='root', password='password', database='tut' ) # 创建游标对象 cursorObj = connection.cursor() # 创建包含小数列的表 sql = ''' CREATE TABLE EMPLOYEES ( ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, SALARY decimal(14,4) NOT NULL, PRIMARY KEY (ID) )''' cursorObj.execute(sql) print("The table is created successfully!") # 需要插入的数据 data_to_insert = [ ('Krishna', 150050.34), ('Kalyan', 100000.65) ] # 向创建的表中插入数据 insert_query = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES (%s, %s)" cursorObj.executemany(insert_query, data_to_insert) # 插入操作后提交更改 connection.commit() print("Rows inserted successfully.") # 现在显示表记录 select_query = "SELECT * FROM EMPLOYEES" cursorObj.execute(select_query) result = cursorObj.fetchall() print("Table Data:") for row in result: print(row) cursorObj.close() connection.close()
输出
以下是上述代码的输出 -
The table is created successfully! Rows inserted successfully. Table Data: (1, 'Krishna', Decimal('150050.3400')) (2, 'Kalyan', Decimal('100000.6500'))