【Sqlite3】maraidb和sqlite3部分命令操作区别

这篇具有很好参考价值的文章主要介绍了【Sqlite3】maraidb和sqlite3部分命令操作区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

maraidb和sqlite3部分命令操作区别记录

1.安装sqlite3

在实现我的视频点播系统项目时,我尝试封装了两种数据库的调用逻辑

  • mysql(maraidb)
  • sqlite3

这里封装sqlite3的原因是,sqlite3主要针对的就是嵌入式数据库,其性能可能不如mysql,但是就好在可以带着走。安装也很方便,内存占用相对于mariadb来说也降低了很多。

教程:安装maraidb

在上面的博客中,安装maraidb需要很多步骤,还需要修改配置文件中的默认字符集为UTF8。

而安装sqlite3就要多方便有方便了,而且sqlite3默认采用的就是uft8字符集,完全不需要修改!

sudo yum install sqlite-devel

就这一行命令就搞定了!

sqlite3 --version #查看当前安装的版本

安装完成后,可以看看sqlite3的版本(如果没有安装,执行这个命令会告知 command not found

[root@1c2261732150:~]# sqlite3 --version
3.26.0 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1

2.基本操作的区别

如下列出一些基本操作在mariadb命令行中,和在sqlite3命令行中的区别

为了方便,注释中m指代mysql,s指代sqlite3

show databases; -- 查看所有数据库 mariadb
.database       -- 查看当前数据库 sqlite3

use db_name;      -- 进入数据库 m
.open db_name.db; -- 提供.db文件的路径,进入数据库 s

show tables;    -- 查看数据库中所有表 m
.tables         -- 查看数据库中所有表 s

quit  -- 退出数据库命令行 m
.quit -- 退出数据库命令行 s

这便是基础操作的一些区别,更深入的操作我暂时还没有学到。

其中进入数据库的操作就能看出来sqlite的特性,只要有这个.db文件,你就可以很轻松的在另外一个主机上恢复之前的数据(或者进行备份),这也是带着走的体现。

3.创建表

mysql和sqlite3所支持的数据类型也有区别

sqlite3数据类型 描述
NULL 值是一个 NULL 值。
INTEGER 值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。
REAL 值是一个浮点值,存储为 8 字节的 IEEE 浮点数字。
TEXT 值是一个文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储。
BLOB 值是一个 blob 数据,完全根据它的输入存储。

在sqlite3中,没有varchar类型。但我们依旧可以使用TEST(8)来限制字符串类型的长度

以我的视频点播项目所用数据库为例,以下是mariadb创建数据表的sql语句

create table tb_video(
    id VARCHAR(8) NOT NULL DEFAULT (substring(UUID(), 1, 8)) comment '视频id',
    name VARCHAR(50) comment '视频标题',
    info text comment '视频简介',
    video VARCHAR(255) comment '视频链接',
    cover VARCHAR(255) comment '视频封面链接',
    insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '视频创建时间'
);

在这里我采用了mariadb自带的uuid函数来生成uuid字符串,并使用substring函数截取了uuid前8位的内容,作为视频的唯一id

而如果想让mariadb来保证id字段唯一,可以使用如下命令进行约束

create table tb_video(
    id VARCHAR(8) NOT NULL DEFAULT (substring(UUID(), 1, 8)) comment '视频id',
    name VARCHAR(50) comment '视频标题',
    info text comment '视频简介',
    video VARCHAR(255) comment '视频链接',
    cover VARCHAR(255) comment '视频封面链接',
    insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '视频创建时间',
    UNIQUE (id)
);

以下是sqlite3的操作,sqlite3中并不支持comment对字段进行注释。

这里要想让id字段唯一,直接在字段类型后面跟着UNIQUE就可以了

-- sqlite3中不支持uuid函数,所以需要用randomblob函数生成一个随机数,再用hex转成16进制作为视频的id
-- sqlite3默认的时间是utc,所以需要用datetime函数将其转化为东八区的时间
CREATE TABLE IF NOT EXISTS tb_video(
    id TEXT(8) UNIQUE NOT NULL DEFAULT (lower((hex(randomblob(4))))),
    name TEXT NOT NULL,
    info TEXT,
    video TEXT NOT NULL,
    cover TEXT NOT NULL,
    insert_time TIMESTAMP DEFAULT (datetime('now', '+8 hours'))
);

4.插入删除数据

在我项目所用字段中,二者插入/删除数据的操作完全相同,这里就不记录了

-- 删除表
drop table tb_video;
-- 插入数据
insert into tb_video (name, info, video, cover) values ('名字1','说明信息1','test1','testc1');
-- 查看所有字段
select * from tb_video;
select * from tb_video where id='45f78a68'; 
-- 删除数据
delete from tb_video where id = 'D81382A8';

5.使用cpp操作的时候

  • mysql必须要进行init,此时就需要指定目标数据库了
  • 而sqlite3并不需要进行数据库的连接操作,我们就可以实现在cpp中进行数据库的创建、数据表的创建等操作。

c语言操作sqlite3的方法,可以查看菜鸟教程。上面的用例很详细(虽然没有写注释,但还是能看懂的)我就不写博客了~

5.1 查询时的回调

这里只对select命令操作进行说明,在sqlite3中,所有命令都是用下面这个函数来执行的

SQLITE_API int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

如果你执行的是插入、更新等等sql语句,sqlite_callback函数不会被调用(我测试过了)。目前我只发现select语句会调用这个callback函数。

比如我的数据库tb_video中有如下两行数据

df65c8c5|名字1|说明信息1|test1|testc1|2023-05-04 16:57:10
80cd3f51|名字1|说明信息1|test1|testc1|2023-05-04 19:02:05
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

// 每当有结果返回的时候,用这个函数来处理结果
// 第一个参数可以从sqlite3_exec中主动传入
// argc 是结果的行数(二维数组行数)
// argv 是存放数据的二维数组
// azColName 是存放字段名称的二维数组
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
	int i;
	for (i = 0; i < argc; i++)
	{
		printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
	}
	printf("\n");
	return 0;
}
// sqlite3数据库打开测试
void SqliteTest()
{
	sqlite3 *db;// 数据库指针
	char *zErrMsg = 0;
	std::string sql;
	int ret;

	// 打开数据库文件
	if (sqlite3_open("test.db", &db))
	{
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else
	{
		fprintf(stderr, "Opened database successfully\n");
	}

	sql = "select * from tb_video;";
	// 执行sql语句
	ret = sqlite3_exec(db, sql.c_str(), callback, 0, &zErrMsg);
	if (ret != SQLITE_OK)
	{
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else
	{
		fprintf(stdout, "SQL successfully\n");
	}
	sqlite3_close(db);
}

用这个函数来查询,会打印如下的结果。从这个结果中,就能推测出callback函数4个参数分别的作用,已经在代码的注释中说明了。

Opened database successfully
id = df65c8c5
name = 名字1
info = 说明信息1
video = test1
cover = testc1
insert_time = 2023-05-04 16:57:10

id = 80cd3f51
name = 名字1
info = 说明信息1
video = test1
cover = testc1
insert_time = 2023-05-04 19:02:05

其中,第四个参数是给callback函数传入的第一个入参。

5.2 通过回调插入数据到Json字符串

我的视频点播项目在查询的时候,需要将结果保存为json字符串,如果使用mysql的c++操作,就可以直接在遍历结果的二维数组时,将结果放入到Json::Value

        // 查询所有-输出所有视频信息(视频列表)
        bool SelectAll(Json::Value *video_s)
        {
            #define SELET_ALL "select * from %s;"
            std::string sql;
            sql.resize(512);
            sprintf((char*)sql.c_str(),SELET_ALL,_video_table.c_str());
            // 这里加锁是为了保证结果集能被正常报错(并不是防止修改原子性问题,mysql本身就已经维护了原子性)
            // 下方执行语句后,如果不保存结果集 而又执行一次搜索语句,之前搜索的结果就会丢失
            // 加锁是为了保证同一时间只有一个执行流在进行查询操作,避免结果集丢失
            _mutex.lock();
            // 语句执行失败了
            if (!MysqlQuery(_mysql, sql)) {
                _mutex.unlock();
                _log.error("Video SelectAll","query failed");
                return false;
            }
            // 保存结果集到本地
            MYSQL_RES *res = mysql_store_result(_mysql);
            if (res == nullptr) {
                _mutex.unlock();
                _log.error("Video SelectAll","mysql store result failed");
                return false;
            }
            // 遍历结果集,存到json中
            int num_rows = mysql_num_rows(res);//获取结果集的行数
            for (int i = 0; i < num_rows; i++) {
                MYSQL_ROW row = mysql_fetch_row(res);//获取每一行的列数
                Json::Value video;
                video["id"] = row[0];
                video["name"] = row[1];
                video["info"] = row[2];
                video["video"] = row[3];
                video["cover"] = row[4];
                video["insert_time"] = row[5]; //mysql中存放的就是可读时间 (其实存时间戳更好)
                //json list
                video_s->append(video);
            }
            mysql_free_result(res);//释放结果集
            _mutex.unlock();
            _log.info("Video SelectAll","select all finished");
            return true;
        }

而在sqlite3中,就需要使用callback函数的第一个参数来进行json字符串的保存;这里因为sqlite3会给我们返回字段名字,我们就可以直接用字段明作为json的字段名,将参数作为json字段的对应参数。更省事了!

static int callback(void *json_videos, int argc, char **argv, char **azColName)
{
	Json::Value* video_s =  (Json::Value*)json_videos;//转为原本的类型
	Json::Value video;//单个视频
	for (int i = 0; i < argc; i++)
	{
		video[azColName[i]] = argv[i] ? argv[i] : "NULL";//存入数据
		printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
	}
	printf("\n");
	video_s->append(video);//插入到json数组中
	return 0;
}

在主函数中,创建一个Json::Value对象,将其强转为void*的指针,传给callback函数

	// 查询
	Json::Value videos;
	sql = "select * from tb_video;";
	// 执行sql语句
	ret = sqlite3_exec(db, sql.c_str(), callback, (void*)&videos, &zErrMsg);
	if (ret != SQLITE_OK)
	{
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	else
	{
		fprintf(stdout, "Table created successfully\n");
	}
	sqlite3_close(db);

	std::string json_str;
	vod::JsonUtil::Serialize(videos,&json_str);
	std::cout << json_str << std::endl;

编译执行,最终打印的json字符串如下(完整代码见 Github)

[
        {
                "cover" : "testc1",
                "id" : "df65c8c5",
                "info" : "\u8bf4\u660e\u4fe1\u606f1",
                "insert_time" : "2023-05-04 16:57:10",
                "name" : "\u540d\u5b571",
                "video" : "test1"
        },
        {
                "cover" : "testc1",
                "id" : "80cd3f51",
                "info" : "\u8bf4\u660e\u4fe1\u606f1",
                "insert_time" : "2023-05-04 19:02:05",
                "name" : "\u540d\u5b571",
                "video" : "test1"
        }
]

5.3 对表的查询

除了使用sqlite3_exec针对数据库进行操作,还可以用下面这个函数,对指定的表进行查询

int sqlite3_get_table(
  sqlite3* db,              /* 数据库连接 */
  const char *zSql,         /* 查询语句 */
  char ***pazResult,        /* 查询结果 */
  int *pnRow,               /* 查询结果的行数 */
  int *pnColumn,            /* 查询结果的列数 */
  char **pzErrmsg           /* 错误信息 */
);

参数说明如下,这里就比较类似mysql的查询函数了,其会给我们返回结果集,以及结果的行数、列数,让我们自己遍历进行操作。

  • db: 数据库连接对象,是已经打开的数据库连接。
  • zSql: 执行的 SQL 查询语句。
  • pazResult: 一个 char 类型的指针数组(二维,每一行是一个指针,指向一个字符串),用于存储查询结果。每个元素都指向一个表示每行数据的字符串数组。最后一个元素为 NULL。
  • pnRow: 用于存储查询结果的行数。
  • pnColumn: 用于存储查询结果的列数。
  • pzErrmsg: 用于存储错误信息。

sqlite3_get_table 函数执行查询语句时,结果集中的每个单元格都被解释为一个字符串。查询结果将被存储在指针数组 pazResult 中,每行数据占用一个字符串数组(除了最后一个元素为 NULL)。表格的第一行包含列名,后面的每行则为查询结果中的一条记录。

sqlite3_get_table 函数的作用是执行一条 SQL 查询语句,并将其结果存储在一个表格中,以便后续处理和分析。

调用完毕这个函数,处理完结果集后,需要调用如下函数释放结果集

char **pazResult; /* 二维指针数组,存储查询结果 */
int nRow = 0, nColumn = 0;/* 获得查询结果的行数和列数 */
sqlite3_get_table(db, "SELECT * FROM tb_video;", &pazResult, &nRow, &nColumn, NULL);
// 遍历处理结果集
// ....
sqlite3_free_table(pazResult);// 处理完毕结果集后释放

5.3.1 错误示例

如下是一个示例的错误代码!

	char **pazResult; /* 二维指针数组,存储查询结果 */
	/* 获得查询结果的行数和列数 */
	int nRow = 0, nColumn = 0,index=0;
	sqlite3_get_table(db, "SELECT * FROM tb_video;", &pazResult, &nRow, &nColumn, NULL);

	std::cout << nRow << " " <<  nColumn << std::endl;
	for (int i = 0; i < nRow; i++)
	{
		for (int j = 0; j < nColumn; j++)
		{
			printf("%-8s : %-8s\n", pazResult[j],pazResult[i][j]);
		}
    }
	sqlite3_free_table(pazResult);

编译不会出错,但是执行的时候,直接会出现段错误

Opened database successfully
2 6
Segmentation fault

这是因为我们的pazResult只是一个二级指针,我们并没有给他初始化为多少行多少列的模式,导致最终++的时候,会出现访问错位的情况。

如果改成下面这样的打印

			cout <<  pazResult[j] << endl;
			cout << "--" << endl;
			cout << pazResult[i][j] << endl;
			cout << "---" << endl;

打印的结果就是这样的,合计是在遍历每一个字符串!

id
--
i
---
name
--
d
---
info
--

---
video
--

---
cover
--

---
insert_time
--
后面重复的就省略掉了

为什么不行呢?这是因为pazResult实际上的结构是这样的

id
name
info
video
cover
insert_time
df65c8c5
名字1
说明信息1
test1
testc1
2023-05-04 16:57:10

使用pazResult[i][j]进行访问:

  • 当i是0的时候,访问的是id字符串
  • 此时j就变成id字符串里面的下标了
  • nColumn远大于id字符串的长度(id只有两个字符,而在我这里nColumn=6
  • 所以就出现了段错误 Segmentation fault

我还是学艺不精呀!🤣


5.3.2 正确操作

正确的办法应该是这样的

	Json::Value videos;
	char **pazResult; /* 二维指针数组,存储查询结果 */
	/* 获得查询结果的行数和列数 */
	int nRow = 0, nColumn = 0,index=0;
	sqlite3_get_table(db, "SELECT * FROM tb_video;", &pazResult, &nRow, &nColumn, NULL);

	std::cout << nRow <<" " <<  nColumn << std::endl;
	index = nColumn;//从第二列开始,跳过第一行(第一行都是字段名)
	for (int i = 0; i < nRow; i++)
	{
		for (int j = 0; j < nColumn; j++)
		{
             // 前nColumn个数据都是字段名,所以可以用 pazResult[j] 来打印
			printf("%-8s : %-8s\n", pazResult[j],pazResult[index]);
			index++;
		}
	}
	sqlite3_free_table(pazResult);

成功打印出了数据库中两行的数据

Opened database successfully
2 6
id       : df65c8c5
name     : 名字1 
info     : 说明信息1
video    : test1   
cover    : testc1  
insert_time : 2023-05-04 16:57:10
id       : da6d27be
name     : 名字2 
info     : 说明信息2
video    : test2   
cover    : testc2  
insert_time : 2023-05-04 19:59:38

和从数据库命令行中读取到的结果相同

sqlite> select * from tb_video;
df65c8c5|名字1|说明信息1|test1|testc1|2023-05-04 16:57:10
da6d27be|名字2|说明信息2|test2|testc2|2023-05-04 19:59:38

最终的完整代码如下

void SqliteTest()
{
	sqlite3 *db; // 数据库指针
	char *zErrMsg = 0;
	std::string sql;
	int ret;

	// 打开数据库文件
	if (sqlite3_open("test.db", &db))
	{
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		exit(0);
	}
	else
	{
		fprintf(stderr, "Opened database successfully\n");
	}
	// 查询
	Json::Value videos;
	char **pazResult; /* 二维指针数组,存储查询结果 */
	/* 获得查询结果的行数和列数 */
	int nRow = 0, nColumn = 0;
	sqlite3_get_table(db, "SELECT * FROM tb_video;", &pazResult, &nRow, &nColumn, NULL);

	std::cout << nRow <<" " <<  nColumn << std::endl;
	int index = nColumn;//从第二列开始,跳过第一行(第一行都是字段名)
	for (int i = 0; i < nRow; i++)
	{
		Json::Value video;
		for (int j = 0; j < nColumn; j++)
		{
			// 前nColumn个数据都是字段名,所以可以用 pazResult[j] 来打印
			// printf("%-8s : %-8s\n", pazResult[j],pazResult[index]);
			video[pazResult[j]] = pazResult[index] ?pazResult[index] : "NULL"; // 存入数据
			index++;
		}
		// json list
		videos.append(video);
	}

	std::string json_str;
	vod::JsonUtil::Serialize(videos, &json_str);
	std::cout << json_str << std::endl;
	
	sqlite3_free_table(pazResult);
	sqlite3_close(db);
}

完整输出如下,json字符串内的数据是正确的!

Opened database successfully
2 6
[
        {
                "cover" : "testc1",
                "id" : "df65c8c5",
                "info" : "\u8bf4\u660e\u4fe1\u606f1",
                "insert_time" : "2023-05-04 16:57:10",
                "name" : "\u540d\u5b571",
                "video" : "test1"
        },
        {
                "cover" : "testc2",
                "id" : "da6d27be",
                "info" : "\u8bf4\u660e\u4fe1\u606f2",
                "insert_time" : "2023-05-04 19:59:38",
                "name" : "\u540d\u5b572",
                "video" : "test2"
        }
]

sqlite3在返回数据的时候也会给我们返回表中的字段名。我们可以将json字段的key设置成字段名,这样就实现了字段的统一

个人认为,为了避免出现同一value而key不同的情况,最好是将应用层和数据库中的字段统一。否则出现二义性问题不好排查。特别是当一个表中的字段较多的时候。

结语

需要注意的是,二者只是适用范围的区别,并没有孰强孰弱的差距

以下是gpt3.5对二者区别的总结:

SQLite3 和 MySQL 都是流行的关系型数据库管理系统,但它们有不同的用途和设计重点。

  • SQLite3 的主要目标是作为嵌入式数据库使用,包括在移动设备和桌面应用程序中,也可以作为轻量级数据库使用。相比之下,MySQL 的主要重点是支持大型企业级应用程序和高负载服务器。
  • SQLite3 是一个服务器不需要客户端的完全独立的自包含数据库,MySQL 是一个客户端/服务器模型的数据库,需要一个专用的服务器端。
  • SQLite3 支持 SQL-92 标准的基本功能,而 MySQL 支持更广泛的 SQL 标准以及许多扩展功能。
  • SQLite3 的数据存储在单个文件中,而 MySQL 的数据通常存储在多个文件或分布式系统中。

就记录这么多吧!文章来源地址https://www.toymoban.com/news/detail-490637.html

到了这里,关于【Sqlite3】maraidb和sqlite3部分命令操作区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • SQlite3数据库相关相关命令

    SQlite3数据库相关相关命令

    1. 创建表格 2. 插入数据 3. 查看数据库记录 4. 删除信息 5. 更新数据 6. 增加一列 7. 删除一列 (sqlite3 不支持直接删除一列) 1. 打开数据库 2. 关闭数据库 3. 错误信息 4. 执行一条sql语句 5. 查询回调函数 6. 查询函数 小知识:如果结构体中定义的是一级指针,那么你要定义变量取

    2024年02月16日
    浏览(14)
  • sqlite3 是一个命令行工具,用于与 SQLite 数据库进行交互和管理

    sqlite3 example.db sqlite3 new_database.db sqlite3 -init init_script.sql example.db

    2024年02月09日
    浏览(11)
  • 【Linux c】 Sqlite3 操作与功能实现

    一、Sqlite3 数据类型 二、Sqlite3 常用指令操作 三、Sqlite3 API 1. sqlite3_open ( ) 2. sqlite3_errmsg ( ) 3. sqlite3_close ( ) 4. sqlite3_exec ( ) 5. sqlite3_get_table ( ) 6. sqlite3_prepare_v2 ( ) 7. sqlite3_bind ( ) 8. sqlite3_step ( ) 9. sqlite3_finalize ( ) 四、Sqlite3 事务机制 (性能优化) 1. 事务 2. 锁状态 3. SQLITE_BUSY 五、

    2023年04月17日
    浏览(8)
  • 通过C实现sqlite3操作,导入电子词典
  • Python数据库模块sqlite3操作实例(非常实用)

    当使用Python进行SQLite数据库操作时, sqlite3 模块是一个非常常用和强大的工具。它提供了一系列函数和方法,用于创建、连接、查询和管理数据库。下面是一些常见的用法示例:   sqlite-utils 、 sqlitebiter 和其他类似的库可以提供更高级的功能,包括预编译语句的执行优化和数

    2024年02月13日
    浏览(15)
  • django sqlite3操作和manage.py功能介绍

     参考链接:https://www.cnblogs.com/csd97/p/8432715.html manage.py 常用命令_python manage.py_追逐梦想的博客-CSDN博客 python django操作sqlite3_django sqlite_浪子仙迹的博客-CSDN博客

    2024年02月12日
    浏览(9)
  • 通过C实现sqlite3操作,(增删改查),导入电子词典

    一、插入 二、导入电子词典

    2024年02月12日
    浏览(12)
  • 嵌入式中如何用C语言操作sqlite3(07)

    嵌入式中如何用C语言操作sqlite3(07)

    sqlite3编程接口非常多,对于初学者来说,我们暂时只需要掌握常用的几个函数,其他函数自然就知道如何使用了。 本篇假设数据库为my.db,有数据表student。 no name score 4 嵌入式开发爱好者 89.0 创建表格语句如下: sqlite3_open sqlite3_close sqlite3_get_table 举例 下面比如我们要显示st

    2024年02月07日
    浏览(11)
  • Python数据库模块(sqlite3,SQLite3)

    创建数据库:在控制台sqlite3 name sqlite3.connect(database [,timeout ,other optional arguments]) 打开数据库;如果指数据库存在则返回一个连接对象,如果不存在则会创建一个数据库; connection.cursor() 创建一个cursor; cursor.execute(sql) 执行一个sql语句,该语句可以被参数化; connection.execut

    2024年03月19日
    浏览(14)
  • Python3操作SQLite3创建表主键自增长|CRUD基本操作

    Python3操作SQLite3创建表主键自增长|CRUD基本操作

    Win11查看安装的Python路径及安装的库 Python PEP8 代码规范常见问题及解决方案 Python3操作MySQL8.XX创建表|CRUD基本操作 Python3操作SQLite3创建表主键自增长|CRUD基本操作 anaconda3最新版安装|使用详情|Error: Please select a valid Python interpreter Python函数绘图与高等代数互融实例(一):正弦函数与

    2024年02月07日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包