MySQL - DECIMAL



MySQL DECIMAL 数据类型

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 关键字有两个属性:UNSIGNEDZEROFILL

  • 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 个字节。任何剩余的数字都需要额外的存储空间。

剩余(多余)数字所需的存储空间在下表中显示

剩余数字 字节
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 姓名 工资
1 Krishna 150050.3400
2 Kalyan 100000.6500

使用以下查询,我们在“SALARY”列中包含 ZEROFILL 属性:

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 姓名 工资
1 Krishna 0000150050.3400
2 Kalyan 0000100000.6500

Learn MySQL in-depth with real-world projects through our MySQL certification course. Enroll and become a certified expert to boost your career.

使用客户端程序的 DECIMAL 数据类型

我们还可以使用客户端程序创建十进制数据类型的列。

语法

要通过 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/Pythonexecute()函数执行“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.'); //create table with boolean column $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...!\n"); } //insert data into created table $q = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES ('Krishna', 150050.34), ('Kalyan', 100000.65)"; if ($res = $mysqli->query($q)) { printf("Data inserted successfully...!\n"); } //now display the table records $s = "SELECT ID, Salary FROM EMPLOYEES"; if ($r = $mysqli->query($s)) { printf("Table Records: Where Salary is decimal type! \n"); while ($row = $r->fetch_assoc()) { printf(" ID: %d, Salary: %s", $row["ID"], $row["Salary"]); printf("\n"); } } 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", }); //Connecting to MySQL con.connect(function (err) { if (err) throw err; // console.log("Connected successfully...!"); // console.log("--------------------------"); sql = "USE TUTORIALS"; con.query(sql); //create a employees table, that accepts one column of decimal type. 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); //insert data into created table sql = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES ('Krishna', 150050.34), ('Kalyan', 100000.65)"; con.query(sql); //select datatypes of salary 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://127.0.0.1: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 # Establishing the connection connection = mysql.connector.connect( host='localhost', user='root', password='password', database='tut' ) # Creating a cursor object cursorObj = connection.cursor() # Create table with decimal column 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 be inserted data_to_insert = [ ('Krishna', 150050.34), ('Kalyan', 100000.65) ] # Insert data into the created table insert_query = "INSERT INTO EMPLOYEES (NAME, SALARY) VALUES (%s, %s)" cursorObj.executemany(insert_query, data_to_insert) # Commit the changes after the insert operation connection.commit() print("Rows inserted successfully.") # Now display the table records 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'))
广告