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

使用客戶端程式的 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://: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'))
廣告