MySQL - 枚举类型



ENUM(枚举)是一种用户定义的数据类型,它将值列表存储为字符串。这些值在定义 ENUM 列时指定。用户可以在将值插入此列时从此预定义列表中选择值。

在 ENUM 列中定义的每个字符串值都隐式分配一个从 1 开始的数值。MySQL 在内部使用这些数值来表示 ENUM 值。

MySQL ENUM 数据类型

MySQL ENUM 数据类型允许您在插入或更新操作期间从预定义列表中选择一个或多个值。选定的值作为字符串存储在表中,当您从 ENUM 列检索数据时,这些值将以人类可读的格式呈现。

ENUM 列可以接受各种数据类型的值,包括整数、浮点数、十进制数和字符串。但是,在内部,MySQL 会根据其预定义列表将这些值转换为最接近的匹配 ENUM 值。

语法

以下是定义列上 ENUM 数据类型的语法:

CREATE TABLE table_name (  
   Column1,  
   Column2 ENUM ('value1','value2','value3', ...),  
   Column3...  
);

注意:枚举列最多可以有 65,535 个值。

ENUM 的属性

MySQL 中的 ENUM 数据类型具有三个属性。下面描述了相同的内容:

  • 默认值 - 枚举数据类型的默认值为 NULL。如果在插入时未为枚举字段提供值,则将插入 Null 值。

  • NULL - 如果为枚举字段设置此属性,则其工作方式与 DEFAULT 值相同。如果设置,索引值始终为 NULL。

  • NOT NULL - 如果为枚举字段设置此属性,并且在插入时未提供值,则 MySQL 将生成警告消息。

示例

首先,让我们创建一个名为 STUDENTS 的表。在此表中,我们使用以下查询在 BRANCH 列中指定 ENUM 字符串对象:

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)
);

以下是获得的输出:

Query OK, 0 rows affected (0.04 sec)

现在,我们检索 STUDENTS 表的结构,显示“BRANCH”字段具有枚举数据类型:

DESCRIBE STUDENTS;

输出表明 BRANCH 字段的数据类型为 ENUM,它存储值 ('CSE', 'ECE', 'MECH'):

字段 类型 Null 默认值 额外
ID int NO PRI NULL auto_increment
NAME varchar(30) NO NULL
BRANCH enum('CSE','ECE','MECH') YES NULL
FEES int NO NULL

现在,让我们使用以下 INSERT 查询将记录插入 STUDENTS 表中:

INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES
('Anirudh', 'CSE', 500000),
('Yuvan', 'ECE', 350000),
('Harris', 'MECH', 400000);

在这些插入查询中,我们对“BRANCH”字段使用了值 ('CSE', 'ECE' 和 'MECH'),这些都是有效的枚举值。因此,查询在没有任何错误的情况下执行:

Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

使用以下查询,我们可以显示表中的所有值:

SELECT * FROM STUDENTS;

以下是 STUDENTS 表的记录:

ID NAME BRANCH FEES
1 Anirudh CSE 500000
2 Yuvan ECE 350000
3 Harris MECH 400000

使用数值 ENUM 值插入记录

我们可以使用相应的数字索引将枚举列表值插入表的 ENUM 列中。数字索引从 1 开始,而不是从 0 开始。

示例

在下面的查询中,我们使用其数字索引将枚举列表中的值“CSE”插入“BRANCH”列。由于“CSE”位于 ENUM 列表中的位置 1,因此我们在查询中使用 1 作为数字索引。

INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES 
('Devi', 1, 380000);

输出

插入查询在没有任何错误的情况下执行:

Query OK, 1 row affected (0.01 sec)

验证

让我们使用以下查询检索表的所有记录来验证以上插入是否成功:

SELECT * FROM STUDENTS;

显示的 STUDENTS 表如下:

ID NAME BRANCH FEES
1 Anirudh CSE 500000
2 Yuvan ECE 350000
3 Harris MECH 400000
4 Devi CSE 380000

插入无效记录

在 MySQL 中,如果我们尝试将值插入具有 ENUM 数据类型的列中,该值与任何指定的枚举值都不匹配,则会导致错误。

示例

在以下查询中,我们引用了枚举列表中的第 6 个值,该值不存在。因此,以下查询将生成错误:

INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES 
('Thaman', 6, 200000); 

输出

正如我们所看到的输出,生成了一个错误,并且没有插入新记录:

ERROR 1265 (01000): Data truncated for column 'BRANCH' at row 1

按数值 ENUM 值过滤记录

在 MySQL 中,您可以根据字符串值或数字索引从 ENUM 列检索记录。数字索引从 1 开始,而不是 0。

示例

枚举列表中数字索引 1 为“CSE”。因此,以下查询将获取 BRANCH 列包含值为“CSE”的记录。

SELECT * FROM STUDENTS WHERE BRANCH = 1;

输出

生成的输出显示“BRANCH”列包含值“CSE”的记录:

ID NAME BRANCH FEES
1 Anirudh CSE 500000
4 Devi CSE 380000

按人类可读的 ENUM 值过滤记录

枚举列表有时可能包含大量值。记住列表中每个值的数字索引可能很困难。在这种情况下,在查询中使用枚举项的可读字符串值来检索基于枚举字段值的记录会更加方便。

示例

在下面的查询中,我们过滤了 BRANCH 列包含值“Mech”的记录。

SELECT * FROM STUDENTS WHERE BRANCH = "MECH";

输出

以下是获得的输出:

ID NAME BRANCH FEES
3 Harris MECH 400000

ENUM 数据类型的缺点

以下是 MySQL 中枚举数据类型的缺点:

  • 如果我们希望修改枚举列表中的值,我们需要使用 ALTER TABLE 命令重新创建整个表,这在使用的资源和时间方面都非常昂贵。

  • 获取完整的枚举列表非常复杂,因为我们需要访问 inform_schema 数据库。

  • 枚举值不能与表达式一起使用。例如,以下 CREATE 语句将返回错误,因为它使用了 CONCAT() 函数来创建枚举值:

CREATE TABLE Students (  
   ID int PRIMARY KEY AUTO_INCREMENT,   
   NAME varchar(30),   
   BRANCH ENUM('CSE', CONCAT('ME','CH'))
);

用户变量不能用于枚举值。例如,请看以下查询:

mysql> SET @mybranch = 'EEE';  
mysql> CREATE TABLE Students (  
   ID int PRIMARY KEY AUTO_INCREMENT,   
   NAME varchar(30),   
   BRANCH ENUM('CSE', 'MECH', @mybranch)
);

建议不要使用数字值作为枚举值。

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

我们也可以使用客户端程序创建枚举数据类型的列。

语法

要通过 PHP 程序创建枚举数据类型的列,我们需要使用 mysqli 函数 query() 执行“CREATE TABLE”语句,如下所示:

$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))';
$mysqli->query($sql);

要通过 JavaScript 程序创建枚举数据类型的列,我们需要使用 mysql2 库的 query() 函数执行“CREATE TABLE”语句,如下所示:

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) )";
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 STUDENTS( ID int NOT NULL AUTO_INCREMENT,  NAME varchar(30) NOT NULL,  BRANCH ENUM ('CSE', 'ECE', 'MECH'),  FEES int 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 STUDENTS (ID int NOT NULL AUTO_INCREMENT, NAME varchar(30) NOT NULL, BRANCH ENUM ("CSE", "ECE", "MECH"), FEES int NOT NULL, PRIMARY KEY (ID))'; $result = $mysqli->query($sql); if ($result) { printf("Table created successfully...!\n"); } //insert data into created table $q = "INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES ('Anirudh', 'CSE', 500000), ('Yuvan', 'ECE', 350000)"; if ($res = $mysqli->query($q)) { printf("Data inserted successfully...!\n"); } //now display the table records $s = "SELECT BRANCH FROM STUDENTS"; if ($r = $mysqli->query($s)) { printf("Select query executed successfully...!\n"); printf("following records belongs to Enum datatypes: \n"); while ($row = $r->fetch_assoc()) { printf(" Branch Name: %s", $row["BRANCH"]); printf("\n"); } } else { printf('Failed'); } $mysqli->close();

输出

获得的输出如下:

Table created successfully...!
Data inserted successfully...!
Select query executed successfully...!
following records belongs to Enum datatypes:
 Branch Name: CSE
 Branch Name: ECE         
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 customers that accepts one column enum type.
  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) )";
  con.query(sql);

  //insert data into created table
  sql ="INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES ('Anirudh', 'CSE', 500000),  ('Yuvan', 'ECE', 350000)";
  con.query(sql);
  //select datatypes of branch
  sql = `SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'STUDENTS' AND COLUMN_NAME = 'BRANCH'`;
  con.query(sql, function (err, result) {
    if (err) throw err;
    console.log(result);
  });
});  

输出

产生的输出如下:

[ { DATA_TYPE: 'enum' } ]
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Enum {
   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...!");

         //ENUM data types...!;
         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);
         System.out.println("column of a ENUM type created successfully...!");
         ResultSet resultSet = statement.executeQuery("DESCRIBE STUDENTS");
         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 ENUM type created successfully...!
ID int
NAME varchar(30)
BRANCH enum('CSE','ECE','MECH')
FEES int  
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 enum column
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)
);
'''
cursorObj.execute(sql)
print("The table is created successfully!")
# Data to be inserted
data_to_insert = [
    ('Anirudh', 'CSE', 500000),
    ('Yuvan', 'ECE', 350000),
    ('Harris', 'MECH', 400000)
]
# Insert data into the created table
insert_query = "INSERT INTO STUDENTS (NAME, BRANCH, FEES) VALUES (%s, %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 STUDENTS"
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, 'Anirudh', 'CSE', 500000)
(2, 'Yuvan', 'ECE', 350000)
(3, 'Harris', 'MECH', 400000)
广告