MySQL介绍及使用
1. 安装、启动、配置 MySQL
1. 安装 MySQL
更新软件包索引
sudo apt update
安装 MySQL 服务器
sudo apt install mysql-server
安装过程中可能会提示你设置 root 用户密码。如果没有提示,可以跳过,后续可以手动设置。
2. 配置 MySQL
运行安全脚本
安装完成后,运行以下命令以提高 MySQL 的安全性:
sudo mysql_secure_installation
按照提示进行操作:
-
设置 root 用户密码(如果之前未设置)。
-
移除匿名用户(建议选择
Y
)。 -
禁止 root 用户远程登录(如果不需要远程访问,建议选择
Y
)。 -
删除测试数据库(建议选择
Y
)。 -
重新加载权限表(选择
Y
)。
3. 设置 MySQL 用户密码
如果在安装过程中没有设置密码,或者需要更改密码,可以通过以下步骤设置密码。
登录到 MySQL
sudo mysql -uroot -p
如果之前没有设置密码,直接按回车键即可登录。
设置密码
ALTER USER \'root\'@\'localhost\' IDENTIFIED WITH mysql_native_password BY \'新密码\';
将 新密码
替换为你想要设置的密码。
FLUSH PRIVILEGES;
退出 MySQL
exit;
4. 配置远程访问(可选)
如果你需要从其他计算机远程访问 MySQL 数据库,可以按照以下步骤配置。
登录到 MySQL
sudo mysql -uroot -p
创建远程用户并授予权限
CREATE USER \'root\'@\'%\' IDENTIFIED BY \'新密码\';GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'%\';
-
CREATE USER
创建一个允许从任何 IP 地址访问的root
用户。 -
GRANT ALL PRIVILEGES
授予该用户所有数据库和表的完全访问权限。
刷新权限
FLUSH PRIVILEGES;
退出 MySQL
exit;
5. 配置 MySQL 服务:实现所有IP都能访问
编辑 MySQL 配置文件
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
修改 bind-address
bind-address = 127.0.0.1
bind-address = 0.0.0.0
保存并退出
保存文件并退出编辑器。
重启 MySQL 服务
sudo systemctl restart mysql
6. 测试远程访问(可选)
在另一台计算机上,使用以下命令测试远程访问:
mysql -uroot -h[MySQL服务器IP] -p
输入你设置的密码,如果能够成功连接,说明配置成功。
7. 安装 MySQL 客户端(可选)
如果你需要从其他计算机连接到 MySQL 数据库,可以在客户端计算机上安装 MySQL 客户端。
安装 MySQL 客户端
sudo apt install mysql-client
2.MySQL介绍
MySQL 是一个 关系型数据库管理系统(RDBMS),使用 结构化查询语言(SQL) 来管理和操作数据。
“关系”在这里指的是二维表格(表 / table),每张表由行(row) 和 列(column) 组成,数据以结构化形式存储。
1.数值类型
1. 整数类型
TINYINT
SMALLINT
MEDIUMINT
INT
或 INTEGER
BIGINT
2. 浮点数类型
FLOAT
DOUBLE
2、字符串类型
1. 字符类型
CHAR
VARCHAR
2. 二进制字符串类型
BINARY
VARBINARY
3. 文本类型
TINYTEXT
TEXT
MEDIUMTEXT
LONGTEXT
3.MySQL使用
SQL(结构化查询语言) 是操作关系型数据库的标准语言,包括:
-
SELECT
:查询数据 -
INSERT
:插入数据 -
UPDATE
:更新数据 -
DELETE
:删除数据 -
CREATE
/DROP
:创建或删除表和数据库 -
JOIN
:多表联查
1.SQL
1. 登录 MySQL
在终端中输入以下命令登录 MySQL:
mysql -u root -p
-
-u root
表示以管理员用户登录(root
是 MySQL 的默认管理员账号)。 -
-p
表示提示输入密码。输入你在安装过程中设置的 MySQL 管理员密码。
如果密码正确,你会看到 MySQL 的命令行提示符,类似如下:
mysql>
2. 查看数据库
登录后,查看当前数据库列表:
SHOW DATABASES;
你会看到类似以下输出:
+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+
这些是 MySQL 系统自带的数据库。你可以创建自己的数据库。
3. 创建数据库
创建一个新的数据库,例如 mydatabase
:
CREATE DATABASE mydatabase;
4. 切换到新创建的数据库
USE mydatabase;
5. 创建表
在 mydatabase
数据库中创建一个表,例如 students
:
CREATE TABLE students ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT, grade VARCHAR(10));
-
id
是主键,自动递增。 -
name
是字符串类型,最大长度为 50,不能为空。 -
age
是整数类型。 -
grade
是字符串类型,最大长度为 10。
6. 插入数据
向 students
表中插入数据:
INSERT INTO students (name, age, grade) VALUES (\'Alice\', 20, \'A\');INSERT INTO students (name, age, grade) VALUES (\'Bob\', 22, \'B\');
7. 查询数据
查询 students
表中的所有数据:
SELECT * FROM students;
+----+-------+-----+-------+| id | name | age | grade |+----+-------+-----+-------+| 1 | Alice | 20 | A || 2 | Bob | 22 | B |+----+-------+-----+-------+
8. 更新数据
更新表中的数据,例如将 Alice
的年龄改为 21:
UPDATE students SET age = 21 WHERE name = \'Alice\';
9. 删除数据
删除表中的数据,例如删除 Bob
的记录:
sql复制
DELETE FROM students WHERE name = \'Bob\';
再次查询数据,确认删除是否成功:
sql复制
SELECT * FROM students;
10. 退出 MySQL
EXIT;
11. 其他常用操作
-
查看表结构:
DESCRIBE students;
-
删除表:
DROP TABLE students;
-
删除数据库:
DROP DATABASE mydatabase;
- 删除表中所有内容
想删除表中的所有数据,可以使用 TRUNCATE TABLE
或 DELETE
语句。以下是这两种方法的详细说明:
1. TRUNCATE TABLE
TRUNCATE TABLE 表名;
-
速度快:
TRUNCATE TABLE
是一种非常快速的操作,因为它不会逐行删除数据,而是直接删除表中的所有行,然后重新初始化表的存储结构。 -
不可恢复:一旦执行
TRUNCATE TABLE
,表中的数据将无法恢复。这是因为TRUNCATE TABLE
实际上是删除表后再重新创建一个空表,所以不会产生回滚日志。 -
不触发触发器:
TRUNCATE TABLE
不会触发DELETE
触发器,因为它不是逐行删除数据。 -
重置自增列:如果表中包含自增列(
AUTO_INCREMENT
),TRUNCATE TABLE
会将自增列的值重置为初始值(通常是 1)。
2. DELETE
DELETE FROM 表名;
-
特点
-
速度相对较慢:
DELETE
是逐行删除表中的数据,因此速度比TRUNCATE TABLE
慢,尤其是当表中有大量数据时。 -
可恢复:
DELETE
操作会产生回滚日志,因此可以通过事务回滚来恢复数据。 -
触发触发器:如果表上有
DELETE
触发器,DELETE
操作会触发这些触发器。 -
不重置自增列:
DELETE
不会重置表中的自增列,自增列的值会保持在删除前的最大值。
-
2.列的完整性约束
1. 主键约束(Primary Key)
-
作用:唯一标识表中的每条记录。
-
特点:值必须唯一且不能为空。
-
示例:
sql复制
CREATE TABLE students ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50));
2. 外键约束(Foreign Key)
-
作用:建立表与表之间的关系。
-
特点:值必须是另一个表的主键值,或者为空。
-
示例:
sql复制
CREATE TABLE enrollments ( student_id INT, FOREIGN KEY (student_id) REFERENCES students(id));
3. 唯一约束(Unique)
-
作用:确保列中的值是唯一的。
-
特点:允许空值,但每个值必须唯一。
-
示例:
sql复制
CREATE TABLE users ( email VARCHAR(100) UNIQUE);
4. 非空约束(NOT NULL)
-
作用:确保列中的值不能为空。
-
特点:插入或更新时必须提供值。
-
示例:
sql复制
CREATE TABLE employees ( name VARCHAR(50) NOT NULL);
5. 默认值约束(DEFAULT)
-
作用:为列指定默认值。
-
特点:插入记录时未指定值时自动使用默认值。
-
示例:
sql复制
CREATE TABLE orders ( order_date DATE DEFAULT CURRENT_DATE);
6. 检查约束(CHECK)
-
作用:限制列的值必须满足某些条件。
-
特点:确保数据符合特定规则。
-
示例:
sql复制
CREATE TABLE products ( price DECIMAL(10, 2) CHECK (price > 0));
7. 添加和删除约束
-
添加约束:
sql复制
ALTER TABLE table_name ADD CONSTRAINT constraint_name constraint_type;
-
删除约束:
sql复制
ALTER TABLE table_name DROP CONSTRAINT constraint_name;
4.操作 MySQL 的三种主流 C/C++ 接口/库
libmysqlclient-dev
libmysql++
MySQL Connector/C++
1️⃣ libmysqlclient-dev
- 最底层的 C API(推荐了解)
-
作用:提供最基础的
C API
来操作 MySQL。 -
包管理器名(Debian/Ubuntu):
sudo apt install libmysqlclient-dev
-
常用头文件:
#include
-
使用方式:
-
初始化连接
-
发送 SQL 查询
-
获取结果集
-
-
适合:底层开发、嵌入式开发、对性能控制要求高的场景。
#include mysqlpp::Connection conn(false);conn.connect(\"testdb\", \"localhost\", \"root\", \"password\");mysqlpp::Query query = conn.query(\"SELECT * FROM users\");mysqlpp::StoreQueryResult res = query.store();
✅ 优点:轻量、速度快、控制力强
❌ 缺点:接口是 C 风格,写起来繁琐、类型安全差、易出错
2️⃣ libmysql++
- 对 C API 的 C++ 封装(较旧但简单)
-
作用:基于
libmysqlclient
封装,提供更易用的 C++ 接口。 -
安装方式(Ubuntu):
sudo apt install libmysql++-dev
-
项目地址:http://tangentsoft.com/mysql++/
#include mysqlpp::Connection conn(false);conn.connect(\"testdb\", \"localhost\", \"root\", \"password\");mysqlpp::Query query = conn.query(\"SELECT * FROM users\");mysqlpp::StoreQueryResult res = query.store();
✅ 优点:写起来比 C API 简洁
❌ 缺点:项目已经多年未更新,缺乏现代 C++ 特性(比如 smart pointer, exception 安全等)
3️⃣ MySQL Connector/C++
- Oracle 官方的现代 C++ 驱动(推荐)
-
作用:Oracle 提供的官方 C++ 库,支持 C++11/14 风格编程,模块化、支持连接池等。
-
安装方式(Ubuntu):
sudo apt install libmysqlcppconn-dev
-
头文件:
、
等
#include #include #include sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();std::unique_ptr con(driver->connect(\"tcp://127.0.0.1:3306\", \"root\", \"pwd\"));con->setSchema(\"testdb\");std::unique_ptr stmt( con->prepareStatement(\"INSERT INTO users(name) VALUES(?)\"));stmt->setString(1, \"Alice\");stmt->execute();
✅ 优点:
-
支持 prepared statements(防注入)
-
面向对象
-
官方维护,现代设计
❌ 缺点:比 C API 慢一点,依赖较多
✅ 总结:我该选哪个?
libmysqlcppconn-dev
)libmysqlclient-dev
libmysql++
5.C/C++ 使用 MySQL API 操作 数据库
// include/db.hpp#pragma once#include #include struct FileMeta { std::string filename; std::string filepath; std::string user; long size;};bool init_db();void close_db();bool insert_file(const FileMeta &file);std::vector query_files_by_path(const std::string &path);
// src/db.cpp#include \"db.hpp\"#include #include MYSQL *conn = nullptr;bool init_db() { // 1.初始化一个 MySQL 连接句柄 conn = mysql_init(nullptr); if (!conn) { std::cerr << \"mysql_init failed\\n\"; return false; } // 2.建立与 MySQL 数据库 if (!mysql_real_connect(conn, \"127.0.0.1\", \"root\", \"123456\", \"metadb\", 3306, nullptr, 0)) { std::cerr << \"mysql_real_connect failed: \" << mysql_error(conn) << \"\\n\"; return false; } return true;}void close_db() { if (conn) { //关闭与MySQL数据库的连接 mysql_close(conn); conn = nullptr; }}// 向数据库插入文件元数据bool insert_file(const FileMeta &file) { // 1.SQL 插入语句格式化到 query 数组 char query[1024]; snprintf(query, sizeof(query), \"INSERT INTO file_metadata (filename, filepath, user, size) VALUES \" \"(\'%s\', \'%s\', \'%s\', %ld)\", file.filename.c_str(), file.filepath.c_str(), file.user.c_str(), file.size); // 2.mysql_query 函数执行 SQL 查询语句 if (mysql_query(conn, query)) { std::cerr << \"Insert failed: \" << mysql_error(conn) << \"\\n\"; return false; } return true;}std::vector query_files_by_path(const std::string &path) { std::vector results; std::string query = \"SELECT filename, filepath, user, size FROM \"\"file_metadata WHERE filepath = \'\" +path + \"\'\"; if (mysql_query(conn, query.c_str())) { std::cerr << \"Query failed: \" << mysql_error(conn) << \"\\n\"; return results; } // 3.mysql_store_result 函数获取查询结果。 MYSQL_RES *res = mysql_store_result(conn); if (!res) { std::cerr << \"mysql_store_result failed\\n\"; return results; } // 4.mysql_fetch_row 函数逐行获取查询结果 MYSQL_ROW row; while ((row = mysql_fetch_row(res))) { FileMeta file; file.filename = row[0]; file.filepath = row[1]; file.user = row[2]; file.size = std::stol(row[3]); results.push_back(file); } mysql_free_result(res); return results;}
//src/main.cpp#include \"db.hpp\"#include int main() { if (!init_db()) { return 1; } FileMeta file = {\"report.docx\", \"/home/user/docs\", \"alice\", 5120}; insert_file(file); auto files = query_files_by_path(\"/home/user/docs\"); for (const auto &f : files) { std::cout << f.filename << \" (\" << f.size << \" bytes) - \" << f.user << \"\\n\"; } close_db(); return 0;}
cmake_minimum_required(VERSION 3.10)project(MetaFS_C_API)set(CMAKE_CXX_STANDARD 17)set(CMAKE_CXX_STANDARD_REQUIRED True)# 设置头文件路径include_directories(${PROJECT_SOURCE_DIR}/include)# 设置源文件file(GLOB SOURCES ${PROJECT_SOURCE_DIR}/src/*.cpp)# 生成可执行文件add_executable(meta_fs ${SOURCES})# 链接 MySQL client 库target_link_libraries(meta_fs mysqlclient)
——————————————————————————————————————————
#pragma once#include #include struct FileMeta { std::string filename; std::string filepath; std::string user; long size;};bool init_db();bool insert_file(const FileMeta &file);std::vector list_files(const std::string &path);
#include \"db.hpp\"#include //SQL执行#include //查询结果#include #include //链接数据库#include //驱动#include using json = nlohmann::json;static sql::Connection *conn = nullptr;bool init_db() { std::ifstream file(\"config/db_config.json\"); json cfg; file >> cfg; // 1.创建 MySQL 驱动对象,初始化驱动 sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance(); // 2. 建立连接 conn = driver->connect(cfg[\"host\"], cfg[\"user\"], cfg[\"password\"]); // 3. 选择数据库 conn->setSchema(cfg[\"database\"]); return true;}// 将文件元数据插入到数据库中bool insert_file(const FileMeta &file) { // 1.准备SQL语句 sql::PreparedStatement *stmt = conn->prepareStatement(\"INSERT INTO file_metadata(filename, filepath, \" \"user, size) VALUES (?, ?, ?, ?)\"); // 2.设置参数 stmt->setString(1, file.filename); stmt->setString(2, file.filepath); stmt->setString(3, file.user); stmt->setInt64(4, file.size); // 3.执行SQL语句 stmt->execute(); // 4.释放PreparedStatement对象,避免内存泄漏 delete stmt; return true;}//从数据库中查询指定路径下的所有文件元数据,并将结果存储到一个std::vector//中返回std::vector list_files(const std::string &path) { std::vector files; sql::PreparedStatement *stmt = conn->prepareStatement(\"SELECT filename, filepath, user, size FROM \" \"file_metadata WHERE filepath = ?\"); stmt->setString(1, path); // 3.执行查询 sql::ResultSet *res = stmt->executeQuery(); // 4.处理查询结果 while (res->next()) { files.push_back({res->getString(\"filename\"), res->getString(\"filepath\"), res->getString(\"user\"), res->getInt64(\"size\")}); } delete res; delete stmt; return files;}
#include \"db.hpp\"#include int main() { if (!init_db()) { std::cerr << \"DB init failed\\n\"; return 1; } FileMeta f1 = {\"data.txt\", \"/home/user/docs\", \"alice\", 2048}; insert_file(f1); auto files = list_files(\"/home/user/docs\"); for (const auto &f : files) { std::cout << f.filename << \" (\" << f.size << \" bytes) - \" << f.user << \"\\n\"; } return 0;}
-- sql/init.sqlCREATE DATABASE IF NOT EXISTS metadb;USE metadb;CREATE TABLE IF NOT EXISTS file_metadata ( id INT AUTO_INCREMENT PRIMARY KEY, filename VARCHAR(255) NOT NULL, filepath VARCHAR(255) NOT NULL, user VARCHAR(64), create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, size BIGINT);
cmake_minimum_required(VERSION 3.10)project(MiniMetaFS)set(CMAKE_CXX_STANDARD 17)include_directories(include)add_executable(minifs src/main.cpp src/db.cpp)find_package(MySQL REQUIRED)target_link_libraries(minifs mysqlcppconn)# 使用 nlohmann/json(假设你用的是头文件方式)