数据库迁移脚本,使用 Tortoise ORM 定义了数据库的升级和降级操作。它的作用是:
-
创建数据库表结构:定义了多个表(如
api_logs
、apis
、buttons
等),用于存储系统中的各种数据,包括 API 日志、用户信息、角色信息、菜单和按钮的权限等。 -
创建索引:为表中的某些字段创建索引,以提高查询性能。
-
定义表之间的关系:通过外键和多对多关系表,定义了表之间的关联,如角色与菜单、用户与角色等。
后期调整表单是否需要优化 SQL 语句?
如果后期需要调整表单(如添加新字段、修改字段类型、删除字段等),是否需要优化 SQL 语句取决于具体的需求和变更的复杂性:
-
简单变更:如果只是添加新字段或修改字段类型,通常不需要优化 SQL 语句。Tortoise ORM 的迁移工具可以自动生成相应的迁移脚本。
-
复杂变更:如果涉及复杂的表结构调整(如表结构调整、数据迁移等),可能需要手动优化 SQL 语句,以确保迁移的正确性和效率。
-
性能优化:如果发现某些查询性能不佳,可能需要优化索引或调整表结构。
如果不掌握 SQL 语句怎么办?
如果不熟悉 SQL 语句,可以采取以下几种方法来应对:
-
使用 Tortoise ORM 的迁移工具:
-
Tortoise ORM 提供了自动化的迁移工具,可以自动生成迁移脚本。你只需要定义好模型(Model),迁移工具会自动生成相应的 SQL 语句。
-
参考 Tortoise ORM 的官方文档:Tortoise ORM 迁移文档
-
-
使用数据库管理工具:
-
使用图形化的数据库管理工具(如 Navicat、DBeaver、SQL Server Management Studio 等),这些工具提供了直观的界面,可以帮助你生成和执行 SQL 语句。
-
这些工具通常有可视化的设计界面,你可以通过图形化的方式调整表结构,工具会自动生成相应的 SQL 脚本。
-
-
参考现有的迁移脚本:
-
如果项目中已经存在迁移脚本,可以参考这些脚本的结构和内容,学习如何编写和调整 SQL 语句。
-
____________________________________________________________________________
数据库迁移脚本,使用了 Tortoise ORM 来定义数据库的升级和降级操作。它定义了两个异步函数 upgrade
和 downgrade
,分别用于数据库的升级和降级操作。upgrade
函数返回一个 SQL 脚本字符串,用于创建多个表和索引,而 downgrade
函数目前为空,意味着没有定义降级操作。
逐行解读
导入模块
from tortoise import BaseDBAsyncClient
-
导入 Tortoise ORM 中的
BaseDBAsyncClient
类,用于数据库的异步操作。
定义升级函数
async def upgrade(db: BaseDBAsyncClient) -> str:
-
定义一个异步函数
upgrade
,接受一个BaseDBAsyncClient
类型的参数db
,返回一个字符串类型的 SQL 脚本。
创建 API 日志表
return """
CREATE TABLE IF NOT EXISTS "api_logs" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* API日志id */,
"x_request_id" VARCHAR(32) NOT NULL /* 请求id */,
"ip_address" VARCHAR(60) /* IP地址 */,
"user_agent" VARCHAR(500) /* User-Agent */,
"request_domain" VARCHAR(200) NOT NULL /* 请求域名 */,
"request_path" VARCHAR(500) NOT NULL /* 请求路径 */,
"request_params" JSON /* 请求参数 */,
"request_data" JSON /* 请求体数据 */,
"response_data" JSON /* 响应数据 */,
"response_code" VARCHAR(6) /* 业务状态码 */,
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP /* 创建时间 */,
"process_time" REAL /* 请求处理时间 */
) /* API日志 */;
-
创建一个名为
api_logs
的表,用于存储 API 请求和响应的日志信息。表中包含多个字段,如请求 ID、IP 地址、请求路径、请求参数、响应数据等。id
是主键,自动递增。create_time
字段默认值为当前时间戳。
创建 API 日志表的索引
CREATE INDEX IF NOT EXISTS "idx_api_logs_create__a34f2a" ON "api_logs" ("create_time");
CREATE INDEX IF NOT EXISTS "idx_api_logs_process_067c26" ON "api_logs" ("process_time");
CREATE INDEX IF NOT EXISTS "idx_api_logs_x_reque_0dc622" ON "api_logs" ("x_request_id");
CREATE INDEX IF NOT EXISTS "idx_api_logs_request_3eb14c" ON "api_logs" ("request_path");
CREATE INDEX IF NOT EXISTS "idx_api_logs_respons_88b25b" ON "api_logs" ("response_code");
-
为
api_logs
表创建多个索引,分别基于create_time
、process_time
、x_request_id
、request_path
和response_code
字段,以提高查询性能。
创建 API 表
CREATE TABLE IF NOT EXISTS "apis" (
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* API id */,
"api_path" VARCHAR(500) NOT NULL /* API路径 */,
"api_method" VARCHAR(6) NOT NULL /* 请求方法 */,
"summary" VARCHAR(500) /* 请求简介 */,
"tags" JSON /* API标签 */,
"status_type" VARCHAR(1) NOT NULL DEFAULT '1' /* 状态 */
) /* API表 */;
-
创建一个名为
apis
的表,用于存储 API 的相关信息,如路径、请求方法、简介等。id
是主键,自动递增。create_time
和update_time
字段默认值为当前时间戳。
创建 API 表的索引
CREATE INDEX IF NOT EXISTS "idx_apis_api_pat_12f5ea" ON "apis" ("api_path");
CREATE INDEX IF NOT EXISTS "idx_apis_api_met_5933fc" ON "apis" ("api_method");
CREATE INDEX IF NOT EXISTS "idx_apis_summary_8f6762" ON "apis" ("summary");
-
为
apis
表创建索引,分别基于api_path
、api_method
和summary
字段。
创建按钮表
CREATE TABLE IF NOT EXISTS "buttons" (
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* 按钮id */,
"button_code" VARCHAR(200) NOT NULL /* 按钮编码 */,
"button_desc" VARCHAR(200) NOT NULL /* 按钮描述 */,
"status_type" VARCHAR(1) NOT NULL DEFAULT '1' /* 状态 */
);
-
创建一个名为
buttons
的表,用于存储按钮的相关信息,如编码、描述等。id
是主键,自动递增。
创建菜单表
CREATE TABLE IF NOT EXISTS "menus" (
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* 菜单id */,
"menu_name" VARCHAR(100) NOT NULL /* 菜单名称 */,
"menu_type" VARCHAR(1) NOT NULL /* 菜单类型 */,
"route_name" VARCHAR(100) NOT NULL UNIQUE /* 路由名称 */,
"route_path" VARCHAR(200) NOT NULL UNIQUE /* 路由路径 */,
"path_param" VARCHAR(200) /* 路径参数 */,
"route_param" JSON /* 路由参数, List[dict] */,
"order" INT NOT NULL DEFAULT 0 /* 菜单顺序 */,
"component" VARCHAR(100) /* 路由组件 */,
"parent_id" INT NOT NULL DEFAULT 0 /* 父菜单ID */,
"i18n_key" VARCHAR(100) /* 用于国际化的展示文本,优先级高于title */,
"icon" VARCHAR(100) /* 图标名称 */,
"icon_type" VARCHAR(1) /* 图标类型 */,
"href" VARCHAR(200) /* 外链 */,
"multi_tab" INT NOT NULL DEFAULT 0 /* 是否支持多页签 */,
"keep_alive" INT NOT NULL DEFAULT 0 /* 是否缓存 */,
"hide_in_menu" INT NOT NULL DEFAULT 0 /* 是否在菜单隐藏 */,
"fixed_index_in_tab" INT /* 固定在页签的序号 */,
"status_type" VARCHAR(1) NOT NULL DEFAULT '1' /* 菜单状态 */,
"redirect" VARCHAR(200) /* 重定向路径 */,
"props" INT NOT NULL DEFAULT 0 /* 是否为首路由 */,
"constant" INT NOT NULL DEFAULT 0 /* 是否为公共路由 */,
"active_menu_id" INT REFERENCES "menus" ("id") ON DELETE CASCADE /* 隐藏的路由需要激活的菜单 */
) /* 菜单表 */;
-
创建一个名为
menus
的表,用于存储菜单的相关信息,如名称、类型、路由路径等。id
是主键,自动递增。route_name
和route_path
字段具有唯一约束。
创建角色表
CREATE TABLE IF NOT EXISTS "roles" (
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* 角色id */,
"role_name" VARCHAR(20) NOT NULL UNIQUE /* 角色名称 */,
"role_code" VARCHAR(20) NOT NULL UNIQUE /* 角色编码 */,
"role_desc" VARCHAR(500) /* 角色描述 */,
"status_type" VARCHAR(1) NOT NULL DEFAULT '1' /* 状态 */,
"by_role_home_id" INT NOT NULL REFERENCES "menus" ("id") ON DELETE CASCADE /* 角色首页 */
) /* 角色表 */;
-
创建一个名为
roles
的表,用于存储角色的相关信息,如名称、编码、描述等。id
是主键,自动递增。role_name
和role_code
字段具有唯一约束。
创建角色表的索引
CREATE INDEX IF NOT EXISTS "idx_roles_role_na_e92d59" ON "roles" ("role_name");
CREATE INDEX IF NOT EXISTS "idx_roles_role_co_f4cc69" ON "roles" ("role_code");
CREATE INDEX IF NOT EXISTS "idx_roles_status__597955" ON "roles" ("status_type");
-
为
roles
表创建索引,分别基于role_name
、role_code
和status_type
字段。
创建用户表
CREATE TABLE IF NOT EXISTS "users" (
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"update_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* 用户id */,
"user_name" VARCHAR(20) NOT NULL UNIQUE /* 用户名称 */,
"password" VARCHAR(128) NOT NULL /* 密码 */,
"nick_name" VARCHAR(30) /* 昵称 */,
"user_gender" VARCHAR(1) NOT NULL DEFAULT '3' /* 性别 */,
"user_email" VARCHAR(255) UNIQUE /* 邮箱 */,
"user_phone" VARCHAR(20) /* 电话 */,
"last_login" TIMESTAMP /* 最后登录时间 */,
"status_type" VARCHAR(1) NOT NULL DEFAULT '1' /* 状态 */
) /* 用户表 */;
-
创建一个名为
users
的表,用于存储用户的相关信息,如用户名、密码、昵称等。id
是主键,自动递增。user_name
和user_email
字段具有唯一约束。
创建用户表的索引
CREATE INDEX IF NOT EXISTS "idx_users_user_na_7a1e93" ON "users" ("user_name");
CREATE INDEX IF NOT EXISTS "idx_users_nick_na_7d3545" ON "users" ("nick_name");
CREATE INDEX IF NOT EXISTS "idx_users_user_ge_fe41ac" ON "users" ("user_gender");
CREATE INDEX IF NOT EXISTS "idx_users_user_em_d720cf" ON "users" ("user_email");
CREATE INDEX IF NOT EXISTS "idx_users_user_ph_b2a4cb" ON "users" ("user_phone");
CREATE INDEX IF NOT EXISTS "idx_users_status__098c93" ON "users" ("status_type");
-
为
users
表创建索引,分别基于user_name
、nick_name
、user_gender
、user_email
、user_phone
和status_type
字段。
创建日志表
CREATE TABLE IF NOT EXISTS "logs" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL /* 日志id */,
"log_type" VARCHAR(1) NOT NULL /* 日志类型 */,
"log_detail_type" VARCHAR(4) /* 日志详情类型 */,
"create_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP /* 创建时间 */,
"x_request_id" VARCHAR(32) /* 请求id */,
"by_user_id" INT REFERENCES "users" ("id") ON DELETE CASCADE /* 关联专员 */,
"api_log_id" INT UNIQUE REFERENCES "api_logs" ("id") ON DELETE SET NULL /* API日志 */
) /* 日志表 */;
-
创建一个名为
logs
的表,用于存储日志信息,如日志类型、详情类型、创建时间等。id
是主键,自动递增。
创建日志表的索引
CREATE INDEX IF NOT EXISTS "idx_logs_log_typ_88d44b" ON "logs" ("log_type");
CREATE INDEX IF NOT EXISTS "idx_logs_by_user_5fc8d2" ON "logs" ("by_user_id");
CREATE INDEX IF NOT EXISTS "idx_logs_log_det_a9ea91" ON "logs" ("log_detail_type");
CREATE INDEX IF NOT EXISTS "idx_logs_x_reque_99e858" ON "logs" ("x_request_id");
-
为
logs
表创建索引,分别基于log_type
、by_user_id
、log_detail_type
和x_request_id
字段。
创建 Aerich 表
CREATE TABLE IF NOT EXISTS "aerich" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"version" VARCHAR(255) NOT NULL,
"app" VARCHAR(100) NOT NULL,
"content" JSON NOT NULL
);
-
创建一个名为
aerich
的表,用于存储数据库迁移的相关信息,如版本、应用名称、内容等。id
是主键,自动递增。
创建多对多关系表
CREATE TABLE IF NOT EXISTS "menus_buttons" (
"menus_id" INT NOT NULL REFERENCES "menus" ("id") ON DELETE CASCADE,
"button_id" INT NOT NULL REFERENCES "buttons" ("id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "uidx_menus_butto_menus_i_a9336b" ON "menus_buttons" ("menus_id", "button_id");
CREATE TABLE IF NOT EXISTS "roles_apis" (
"roles_id" INT NOT NULL REFERENCES "roles" ("id") ON DELETE CASCADE,
"api_id" INT NOT NULL REFERENCES "apis" ("id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "uidx_roles_apis_roles_i_753aef" ON "roles_apis" ("roles_id", "api_id");
CREATE TABLE IF NOT EXISTS "roles_menus" (
"roles_id" INT NOT NULL REFERENCES "roles" ("id") ON DELETE CASCADE,
"menu_id" INT NOT NULL REFERENCES "menus" ("id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "uidx_roles_menus_roles_i_3d4119" ON "roles_menus" ("roles_id", "menu_id");
CREATE TABLE IF NOT EXISTS "roles_buttons" (
"roles_id" INT NOT NULL REFERENCES "roles" ("id") ON DELETE CASCADE,
"button_id" INT NOT NULL REFERENCES "buttons" ("id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "uidx_roles_butto_roles_i_f9441d" ON "roles_buttons" ("roles_id", "button_id");
CREATE TABLE IF NOT EXISTS "users_roles" (
"users_id" INT NOT NULL REFERENCES "users" ("id") ON DELETE CASCADE,
"role_id" INT NOT NULL REFERENCES "roles" ("id") ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS "uidx_users_roles_users_i_baf5e4" ON "users_roles" ("users_id", "role_id");
-
创建多个多对多关系表,用于存储菜单与按钮、角色与 API、角色与菜单、角色与按钮、用户与角色之间的关系。每个表都包含两个外键字段,分别引用相关表的主键,并创建唯一索引以确保关系的唯一性。
定义降级函数
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
"""
-
定义一个异步函数
downgrade
,接受一个BaseDBAsyncClient
类型的参数db
,返回一个空字符串。这意味着目前没有定义降级操作。