SQLite 数据库入门教程(GO)

宁睿  论坛元老 | 2024-7-15 07:08:49 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1042|帖子 1042|积分 3136

SQLite数据库入门教程

一、SQLite 简介

1、什么是 SQLite?

  SQLite是一个轻量级、嵌入式、跨平台的关系型数据库,是一个进程内的库,实现了自给自足的、无服务器的、零设置的、事务性的 SQL 数据库引擎。它是一个零设置的数据库,这意味着与其他数据库不一样,您不需要在体系中设置。就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用步伐需求进行静态或动态连接。SQLite 直接访问其存储文件。
2、为什么要用 SQLite?



  • 不需要一个单独的服务器进程或操作的体系(无服务器的)。它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。
  • SQLite 不需要设置,这意味着不需要安装或管理。
  • 一个完备的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。使用 sqlite 打开或创建一个数据库文件,操作该文件实现对数据库的操作。
  • SQLite 黑白常小的,是轻量级的,完全设置时小于 400KiB,省略可选功能设置时小于250KiB。
  • SQLite 是自给自足的,它的焦点引擎自己不依赖第三方的软件。
  • SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。
  • SQLite 支持 SQL92(SQL2)尺度的大多数查询语言的功能。
  • SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。
  • SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行。
二、SQLite 安装

1、在 Windows 上安装 SQLite

   请访问 SQLite 下载页面,从 Windows 区下载预编译的二进制文件,你需要下载 sqlite-dll-win64-x64-3420000.zip 和 sqlite-tools-win32-x86-3420000.zip 压缩文件。

   新建文件夹 D:\SQLite,并在此文件夹中解压上面两个压缩文件,将得到以下文件。

   添加 D:\SQLite 到 PATH 环境变量,最后在命令提示符下,使用 sqlite3 命令,将表现如下结果。

2、在 Linux 、Mac OS上安装 SQLite

   Linux 操作体系、Mac OS 体系都附带 SQLite,使用 sqlite3 命令来检查你的呆板上是否已经安装了 SQLite。如果没有可用的安装,请访问 SQLite 下载页面,从源代码区下载 sqlite-autoconf-3420000.tar.gz。

使用如下步骤安装:
  1. $ tar xvzf sqlite-autoconf-3420000.tar.gz
  2. $ cd sqlite-autoconf-3420000
  3. $ ./configure --prefix=/usr/local
  4. $ make
  5. $ make install
复制代码
三、SQLite 命令

  在 sqlite> 提示符后可以输入命令,这些命令被称为 SQLite 的点命令。确保 sqlite> 提示符与点命令之间没有空格,否则将无法正常工作。SQLite 是不区分大小写的,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义。
命令描述.help获取可用的点命令的清单.exit退出 SQLite 提示符.show表现各种设置的当前值.quit退出 SQLite 提示符.databases列出数据库的名称及其所依附的文件.schema查察所有表结构.schema 表名查察指定表结构.tables查察所有表.tables 表名查察指定表,表存在返回表名,表不存在什么都不返回.header(s) ON/OFF开启或关闭头部表现.mode MODE设置输出模式,MODE 可以是下列之一:column 左对齐的列.timer ON/OFF开启或关闭 CPU 定时器


四、SQLite 使用

1、SQLite 数据范例

  SQLite 数据范例是一个用来指定任何对象的数据范例的属性。SQLite 中的每一列,每个变量和表达式都有相关的数据范例。您可以在创建表的同时使用这些数据范例。SQLite 使用一个更普遍的动态范例体系。在 SQLite 中,值的数据范例与值自己是相关的,而不是与它的容器相关。
存储类描述NULL值是一个 NULL 值INTEGER值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中REAL值是一个浮点值,存储为 8 字节的 IEEE 浮点数字TEXT值是一个文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储BLOB值是一个 blob 数据,完全根据它的输入存储 2、SQLite 语法

  所有的 SQLite 语句可以以任何关键字开始,如 SELECT、INSERT、UPDATE、DELETE、ALTER、DROP 等,所有的语句以分号 ; 竣事。


  • 创建数据库:sqlite3 DatabaseName.db
  1. C:\Users\lenovo>sqlite3 C:\Users\lenovo\Desktop\test.db // 创建数据库
  2. sqlite> .databases // 显示数据库信息
  3. sqlite> .quit // 退出sqlite3的shell程序环境
  4. sqlite> .open test.db // 创建数据库
复制代码

     新手注意,这里有一个坑,是在cmd(在命令行)中输入,而不是打开sqlite3后在shell中输入。输入 .databases 就会表现刚创建的数据库信息(能看到创建的数据库文件及地址路径信息);输入.quit 就会退出sqlite3的shell步伐环境。进入SQLite后,输入 .open 数据库名.db 方式,也可以创建数据库,如果数据库文件已经建立,则打开。这种方式不支持自界说路径。
  

  • 创建表:CREATE TABLE database_name.table_name(column1 datatype PRIMARY KEY(one or more columns),column2 datatype,…);
  1. sqlite> CREATE TABLE express_orders (id INTEGER PRIMARY KEY NOT NULL,uid INTEGER NOT NULL,weight DOUBLE NOT NULL,created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP); // 创建表
  2. sqlite> .schema // 查看所有表结构
  3. sqlite> .tables // 查看所有表
复制代码



  • 插入数据(insert):
    INSERT INTO TABLE_NAME (column1, column2, column3,…columnN) VALUES (value1, value2, value3,…valueN);
    INSERT INTO TABLE_NAME VALUES (value1,value2,value3,…valueN);

  1. sqlite> INSERT INTO express_orders (uid,weight) VALUES (1685040228039,0.9);
  2. sqlite> INSERT INTO express_orders (uid,weight) VALUES (1685040500698,67.9942);
  3. sqlite> INSERT INTO express_orders (uid,weight) VALUES (1685040524994,99.99);
  4. sqlite> INSERT INTO express_orders (uid,weight) VALUES (1685040559781,100);
复制代码



  • 查询数据(select):
    SELECT * FROM table_name;(查询所有字段)
    SELECT column1, column2, columnN FROM table_name;(查询指定字段)
    SELECT * FROM table_name where column1 = 指定信息;(在限制条件下查询指定信息)
  1. sqlite> SELECT * FROM express_orders;
  2. sqlite> SELECT uid,weight FROM express_orders;
  3. sqlite> SELECT * FROM express_orders where id > 1;
  4. sqlite> .header on // 开启头部显示
  5. sqlite> .mode column // 设置输出模式,左对齐的列
  6. sqlite> SELECT * FROM express_orders;
  7. sqlite> .timer on // 开启 CPU 定时器
  8. sqlite> SELECT * FROM express_orders;
复制代码




  • 创建索引(Index):CREATE INDEX index_name ON table_name (column_name);
  1. sqlite> CREATE INDEX index_uid ON express_orders (uid); // 创建索引
  2. sqlite> .schema // 查看所有表结构
复制代码

3、SQLite 可视化管理工具

  SQLiteStudio是一个开源、跨平台的 SQLite 可视化管理工具。免费,多语言界面,支持 Linux,Mac 和 Windows。官方网址SQLiteStudio。


五、Go 语言使用 SQLite 数据库

1、安装 go-sqlite3

  在安装go-sqlite3之前,需要先安装SQLite数据库,在Golang中通过 go get 命令安装 go-sqlite3:
  1. go get github.com/mattn/go-sqlite3
复制代码
2、安装 mingw64

  在实践中我们发现,只安装 go-sqlite3 是不可以的,无法和数据库建立连接,会报以下错误:
  1. # github.com/mattn/go-sqlite3
  2. cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in %PATH%
复制代码
  报错意思是缺少 gcc 环境,我们需要装一个 gcc 环境。因为 go内里使用sqlite,实际上是要下载sqlite的源代码编译的,固然,使用的时候不用手动编译,在linux中,gcc 如果已经安装了,是不用担心的,但是在windows中,为了支持编译,必须使用 mingw64。下载后缀为 posix-seh 的,mingw64下载地址。

  解压下载好的文件放置任一目录,随后将 bin 目录添加进 path 环境变量中,打开 cmd ,输入 gcc -v ,如正确表现版本号则安装成功,然后重启 goland 即可。
  如果你发现在 cmd 中已经能够找到 gcc 命令,但是goland 中执行步伐照旧找不到的话,那么多半就是 goland 的环境变量还未革新,重启电脑、大概清空goland全部缓存并重启,即可解决。

3、连接数据库

  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         // 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
  6.         _ "github.com/mattn/go-sqlite3"
  7.         "log"
  8. )
  9. var db *sql.DB
  10. var err error
  11. func main() {
  12.         // Open() 函数指定驱动名称和数据源名称
  13.         db, err = sql.Open("sqlite3", "data.db")
  14.         if err != nil {
  15.                 fmt.Printf("Database creation failed: %v\n", err)
  16.                 return
  17.         }
  18.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  19.         defer db.Close()
  20.         var version string
  21.         // QueryRow() 执行查询,返回版本号
  22.         err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
  23.         if err != nil {
  24.                 fmt.Printf("Database creation failed: %v\n", err)
  25.                 return
  26.         }
  27.         // 连接成功,打印出"database connected:版本号"
  28.         fmt.Printf("Database creation successful: %v\n", version)
  29. }
复制代码

4、创建数据表

  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         // 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
  6.         _ "github.com/mattn/go-sqlite3"
  7. )
  8. func main() {
  9.         // Open() 函数指定驱动名称和数据源名称
  10.         db, err = sql.Open("sqlite3", "data.db")
  11.         if err != nil {
  12.                 fmt.Printf("Database creation failed: %v\n", err)
  13.                 return
  14.         }
  15.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  16.         defer db.Close()
  17.         connectDB()
  18.         createTable()
  19. }
  20. var db *sql.DB
  21. var err error
  22. // 连接数据库
  23. func connectDB() {
  24.         var version string
  25.         // QueryRow() 执行查询,返回版本号
  26.         err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
  27.         if err != nil {
  28.                 fmt.Printf("Database creation failed: %v\n", err)
  29.                 return
  30.         }
  31.         // 连接成功,打印出"database connected:版本号"
  32.         fmt.Printf("Database creation successful: %v\n", version)
  33. }
  34. // 创建数据库表
  35. func createTable() {
  36.         // 建表语句
  37.         sts := `
  38.     CREATE TABLE express_orders (
  39.         id INTEGER PRIMARY KEY NOT NULL,
  40.         uid INTEGER NOT NULL,
  41.         weight DOUBLE NOT NULL,
  42.         created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  43.     );`
  44.         // 使用db.Exec() 函数来执行 SQL 语句
  45.         _, err = db.Exec(sts)
  46.         if err != nil {
  47.                 fmt.Printf("Failed to create database table: %v\n", err)
  48.                 return
  49.         }
  50.         fmt.Printf("Successfully created database table! \n")
  51. }
复制代码

5、插入数据

  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         // 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
  6.         _ "github.com/mattn/go-sqlite3"
  7. )
  8. func main() {
  9.         // Open() 函数指定驱动名称和数据源名称
  10.         db, err = sql.Open("sqlite3", "data.db")
  11.         if err != nil {
  12.                 fmt.Printf("Database creation failed: %v\n", err)
  13.                 return
  14.         }
  15.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  16.         defer db.Close()
  17.         connectDB()
  18.         insert(1, 0.81192)
  19. }
  20. var db *sql.DB
  21. var err error
  22. // 连接数据库
  23. func connectDB() {
  24.         var version string
  25.         // QueryRow() 执行查询,返回版本号
  26.         err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
  27.         if err != nil {
  28.                 fmt.Printf("Database creation failed: %v\n", err)
  29.                 return
  30.         }
  31.         // 连接成功,打印出"database connected:版本号"
  32.         fmt.Printf("Database creation successful: %v\n", version)
  33. }
  34. // 插入数据
  35. func insert(uid int, weight float64) {
  36.         // 插入语句
  37.         res, err := db.Exec("INSERT INTO express_orders(uid, weight) VALUES(?,?)", uid, weight)
  38.         if err != nil {
  39.                 fmt.Printf("Insert data failed: %v\n", err)
  40.                 return
  41.         }
  42.         // 获取自增ID
  43.         lastInsertId, _ := res.LastInsertId()
  44.         fmt.Printf("Successfully inserted data, lastInsertId =  %v\n", lastInsertId)
  45. }
复制代码

6、查询数据

  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         // 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
  6.         _ "github.com/mattn/go-sqlite3"
  7. )
  8. func main() {
  9.         // Open() 函数指定驱动名称和数据源名称
  10.         db, err = sql.Open("sqlite3", "data.db")
  11.         if err != nil {
  12.                 fmt.Printf("Database creation failed: %v\n", err)
  13.                 return
  14.         }
  15.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  16.         defer db.Close()
  17.         connectDB()
  18.         ret := query(1)
  19.         fmt.Println(ret)
  20. }
  21. var db *sql.DB
  22. var err error
  23. // 连接数据库
  24. func connectDB() {
  25.         var version string
  26.         // QueryRow() 执行查询,返回版本号
  27.         err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
  28.         if err != nil {
  29.                 fmt.Printf("Database creation failed: %v\n", err)
  30.                 return
  31.         }
  32.         // 连接成功,打印出"database connected:版本号"
  33.         fmt.Printf("Database creation successful: %v\n", version)
  34. }
  35. // 查询数据
  36. func query(uid int) (weightList []float64) {
  37.         // 结果重量集合
  38.         weightList = make([]float64, 0)
  39.         // 查询语句
  40.         rows, err := db.Query("SELECT weight FROM express_orders WHERE uid = ?", uid)
  41.         if err != nil {
  42.                 fmt.Printf("Failed to query data: %v\n", err)
  43.                 return
  44.         }
  45.         for rows.Next() {
  46.                 var weight float64
  47.                 err = rows.Scan(&weight)
  48.                 if err != nil {
  49.                         fmt.Printf("Failed to read data: %v\n", err)
  50.                         continue
  51.                 }
  52.                 weightList = append(weightList, weight)
  53.         }
  54.         return weightList
  55. }
复制代码

六、实践(运费清单计算和测试步伐)


题目 1 代码如下:
  1. package main
  2. import (
  3.         "fmt"
  4.         "math"
  5. )
  6. func main() {
  7.         var weight float64
  8.         fmt.Print("请输入实际重量(单位:KG):")
  9.         fmt.Scanf("%f", &weight)
  10.         if weight > 0 && weight <= 100 {
  11.                 fee := compute(weight)
  12.                 fmt.Printf("快递费用为 %d 元。\n", fee)
  13.         } else {
  14.                 fmt.Println("实际重量输入错误!!!")
  15.         }
  16. }
  17. // 计算快递费用
  18. func compute(number float64) int {
  19.         // 快递费用
  20.         fee := 0
  21.         // 计费重量,实际重量向上取整
  22.         weight := int(math.Ceil(number))
  23.         // 计算费用
  24.         switch weight == 1 {
  25.         case false:
  26.                 newFee := float64(18)
  27.                 for i := 2; i <= weight; i++ {
  28.                         newFee = 5 + newFee*1.01
  29.                 }
  30.                 newFee = math.Round(newFee)
  31.                 fee = int(newFee)
  32.         default:
  33.                 fee = 18
  34.         }
  35.         return fee
  36. }
复制代码
测试:输入0

测试:输入0.81192

测试:输入2.996

测试:输入99.99

测试:输入100

测试:输入101

题目 2 :
生成数据的代码:
  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5.         "math/rand"
  6.         "sort"
  7.         "sync"
  8.         // 导入包,导入前缀为下划线,则init函数被执行,然后注册驱动。
  9.         _ "github.com/mattn/go-sqlite3"
  10. )
  11. var db *sql.DB
  12. var err error
  13. func main() {
  14.         db, err = sql.Open("sqlite3", "data.db")
  15.         if err != nil {
  16.                 fmt.Printf("Database creation failed: %v\n", err)
  17.                 return
  18.         }
  19.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  20.         defer db.Close()
  21.         // 连接数据库
  22.         connectDB()
  23.         // 创建数据库表
  24.         //createTable()
  25.         // 生成 1000 个用户 id
  26.         createUid()
  27.         var wg sync.WaitGroup
  28.         wg.Add(10)
  29.         // 创建 10 个协程,同时往数据库里插数据
  30.         for i := 0; i < 10; i++ {
  31.                 go func() {
  32.                         // 生成 100000 条订单记录并插入数据库中
  33.                         createRecords()
  34.                 }()
  35.         }
  36.         wg.Wait()
  37. }
  38. // 用户 id
  39. var uidList = make([]int, 1000)
  40. // 生成 1000 个用户 id
  41. func createUid() {
  42.         for i := 0; i < 1000; i++ {
  43.                 uidList[i] = i + 1
  44.         }
  45. }
  46. // 生成 100000 条订单记录并插入数据库中
  47. func createRecords() {
  48.         // 值数组
  49.         valueList := make([]int, 100)
  50.         // 权重数组
  51.         weightList := make([]float64, 100)
  52.         for i := 0; i < 100; i++ {
  53.                 valueList[i] = 100 - i
  54.                 // 权重递增排序
  55.                 weightList[i] = 1 / float64(100-i)
  56.         }
  57.         // 加权
  58.         totals := make([]float64, 100)
  59.         // 总权重
  60.         weightTotal := float64(0)
  61.         for i, weight := range weightList {
  62.                 weightTotal += weight
  63.                 totals[i] = weightTotal
  64.         }
  65.         // 插入 10000 条订单记录
  66.         for i := 0; i < 10000; i++ {
  67.                 // 生成一个 1000 以内的整形随机数(包含 0 )
  68.                 n := rand.Intn(1000)
  69.                 // 取用户 id
  70.                 uid := uidList[n]
  71.                 // 使用总权重获取随机数,避免超过范围,随机生成的数需要排除0,故加 0.01
  72.                 num := rand.Float64()*weightTotal + 0.01
  73.                 // 核心点,使用二分法,找到对应的下标,如果没有则为大于该数的+1 下标,可能为len(a)即数组长度
  74.                 index := sort.SearchFloat64s(totals, num)
  75.                 // 根据下标去值数组中取数,放到结果数组中
  76.                 weight := valueList[index%100]
  77.                 insert(uid, weight)
  78.         }
  79. }
  80. // 连接数据库
  81. func connectDB() {
  82.         var version string
  83.         // QueryRow() 执行查询,返回版本号
  84.         err = db.QueryRow("SELECT SQLITE_VERSION()").Scan(&version)
  85.         if err != nil {
  86.                 fmt.Printf("Database creation failed: %v\n", err)
  87.                 return
  88.         }
  89.         // 连接成功,打印出"database connected:版本号"
  90.         fmt.Printf("Database creation successful: %v\n", version)
  91. }
  92. // 创建数据库表
  93. func createTable() {
  94.         // 建表语句
  95.         sts := `
  96.     CREATE TABLE express_orders (
  97.         id INTEGER PRIMARY KEY NOT NULL,
  98.         uid INTEGER NOT NULL,
  99.         weight DOUBLE NOT NULL,
  100.         created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
  101.     );`
  102.         // 使用db.Exec() 函数来执行 SQL 语句
  103.         _, err = db.Exec(sts)
  104.         if err != nil {
  105.                 fmt.Printf("Failed to create database table: %v\n", err)
  106.                 return
  107.         }
  108.         fmt.Printf("Successfully created database table! \n")
  109. }
  110. // 插入数据
  111. func insert(uid int, weight int) {
  112.         // 插入语句
  113.         res, err := db.Exec("INSERT INTO express_orders(uid, weight) VALUES(?,?)", uid, weight)
  114.         if err != nil {
  115.                 fmt.Printf("Insert data failed: %v\n", err)
  116.                 return
  117.         }
  118.         // 获取自增ID
  119.         lastInsertId, _ := res.LastInsertId()
  120.         fmt.Printf("Successfully inserted data, lastInsertId =  %v\n", lastInsertId)
  121. }
复制代码

查询功能的代码:
  1. package main
  2. import (
  3.         "database/sql"
  4.         "fmt"
  5. )
  6. type order struct {
  7.         id         int
  8.         uid        int
  9.         weight     float64
  10.         createTime string
  11. }
  12. func main() {
  13.         var uid int
  14.         fmt.Print("请输入 1 个用户 id:")
  15.         fmt.Scanf("%f", &uid)
  16.         db, err = sql.Open("sqlite3", "data.db")
  17.         if err != nil {
  18.                 fmt.Printf("Database creation failed: %v\n", err)
  19.                 return
  20.         }
  21.         // 调用db.Close() 函数,确保关闭数据库并阻止启动新的查询
  22.         defer db.Close()
  23.        
  24.         weightList := query(uid)
  25.         fmt.Println(weightList)
  26.         cost := 0
  27.         for _, val := range weightList {
  28.                 fee := compute(val.weight)
  29.                 cost += fee
  30.         }
  31.         fmt.Printf("该用户总的快递费用为 %d 元。\n", cost)
  32. }
  33. // 查询数据
  34. func query(uid int) (weightList []order) {
  35.         // 结果重量集合
  36.         weightList = make([]order, 0)
  37.         // 查询语句
  38.         rows, err := db.Query("SELECT weight FROM express_orders WHERE uid = ?", uid)
  39.         if err != nil {
  40.                 fmt.Printf("Failed to query data: %v\n", err)
  41.                 return
  42.         }
  43.         defer rows.Close()
  44.         fmt.Println(rows.Next())
  45.         fmt.Println(rows.Columns())
  46.         for rows.Next() {
  47.                 var id int
  48.                 var weight float64
  49.                 var createTime string
  50.                 err = rows.Scan(&id, &uid, &weight, &createTime)
  51.                 if err != nil {
  52.                         fmt.Printf("Failed to read data: %v\n", err)
  53.                         continue
  54.                 }
  55.                 fmt.Println(id, uid)
  56.                 orderRow := order{id: id, uid: uid, weight: weight, createTime: createTime}
  57.                 weightList = append(weightList, orderRow)
  58.         }
  59.         return weightList
  60. }
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表