sqlite3 插入问题处理

用insert语句插入数据,为避免重复插入又不打断数据处理。
首先要避免重复插入,就必须在插入时引发冲突。在表中设置了id字段,该字段为UNIQUE属性,当插入的id已存在时引发冲突。
引发冲突后insert会做一些处理,处理方式由OR字句定义。包含如下:

ROLLBACK
当发生约束冲突,立即ROLLBACK,即结束当前事务处理,命令中止并返回SQLITE_CONSTRAINT代码。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。

ABORT
当发生约束冲突,命令收回已经引起的改变并中止返回SQLITE_CONSTRAINT。但由于不执行ROLLBACK,所以前面的命令产生的改变将予以保留。缺省采用这一行为。

FAIL
当发生约束冲突,命令中止返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留。例如,若一条UPDATE语句在100行遇到冲突100th,前99行的改变将被保留,而对100行或以后的改变将不会发生。

IGNORE
当发生约束冲突,发生冲突的行将不会被插入或改变。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。

REPLACE
当发生UNIQUE约束冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法

为避免操作打断,我选择了IGNORE。最后完整的用法如下:

create table test(
    id integer primary key AUTOINCREMENT,
    s1 text not null default "",
    s2 text not null default "",
    s3 text not null default "",
    s4 text not null default "",
    s5 text not null default "",
    s6 text not null default "1900-01-01 08:00:00",
    s7 text not null default "",
    status text not null default "",
    unique(s1, status)
    );
sqlite> insert  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
sqlite> select * from test
   ...> ;
1|1|||||1900-01-01 08:00:00||0
2|2|||||1900-01-01 08:00:00||0
3|2|||||1900-01-01 08:00:00||1

ignore
ignore 插入新数据~时忽略,冲突不会报错,也不执行更新;

sqlite> insert  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
Error: UNIQUE constraint failed: test.s1, test.status
sqlite> insert or ignore  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
sqlite> select * from test
   ...> ;
1|1|||||1900-01-01 08:00:00||0
2|2|||||1900-01-01 08:00:00||0
3|2|||||1900-01-01 08:00:00||1

replace
数据被删除,插入新数据,id更新了

sqlite> insert or replace  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
sqlite> select * from test;
7|1|||||1900-01-01 08:00:00||0
8|2|||||1900-01-01 08:00:00||0
9|2|||||1900-01-01 08:00:00||1

rollback、fail、abort
中断操作

sqlite> insert or abort  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
Error: UNIQUE constraint failed: test.s1, test.status
sqlite> insert or fail  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
Error: UNIQUE constraint failed: test.s1, test.status
sqlite> insert or rollback  into test(s1, status) values("1", "0"),("2", "0"),("2", "1");
Error: UNIQUE constraint failed: test.s1, test.status

last_insert_rowid
获取最后插入的id

sqlite> .headers on
sqlite> select last_insert_rowid() as id from test;
id
9
9
9
sqlite> .mode column
sqlite> select last_insert_rowid() as id from test;
id
----------
9
9
9
sqlite> select distinct last_insert_rowid() as id from test;
id
----------
9
在 C++ 中使用 SQLite3 插入数据通常需要以下几个步骤: 1. **连接数据库**: 首先,你需要包含 SQLite 的头文件,并通过 `sqlite3_open_v2` 函数打开数据库。例如: ```cpp sqlite3* db; int rc = sqlite3_open("example.db", &db); if (rc) { // 处理错误 } ``` 2. **创建或选择表**: 确保你要插入数据的表已经存在。如果不存在,可以使用 SQL 创建命令创建它。比如创建一个简单的用户表: ```cpp const char* create_table_sql = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT);"; if (sqlite3_exec(db, create_table_sql, nullptr, nullptr, nullptr) != SQLITE_OK) { // 处理错误 } ``` 3. **准备 SQL 语句**: 使用 `sqlite3_prepare_v2` 准备插入数据的 SQL 语句。这里是一个插入示例: ```cpp const char* insert_sql = "INSERT INTO users (name, email) VALUES (?, ?)"; sqlite3_stmt* stmt; rc = sqlite3_prepare_v2(db, insert_sql, -1, &stmt, nullptr); if (rc != SQLITE_OK) { // 处理错误 } ``` 4. **绑定参数**: 对于每个要插入的数据项,你可以使用 `sqlite3_bind_text` 或者其他适当的函数绑定到 SQL 语句中对应的占位符。例如,插入字符串和整数: ```cpp std::string name = "John Doe"; std::string email = "john.doe@example.com"; sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 2, email.c_str(), -1, SQLITE_TRANSIENT); ``` 5. **执行 SQL**: 调用 `sqlite3_step` 执行 SQL 语句。如果成功,`SQLITE_DONE` 表示操作完成;如果有错误,处理错误。 ```cpp while (sqlite3_step(stmt) == SQLITE_ROW) { // 操作已完成,无需做任何事情 } if (sqlite3_step(stmt) != SQLITE_DONE) { // 处理错误 } ``` 6. **清理资源**: 最后,记得释放资源: ```cpp sqlite3_finalize(stmt); sqlite3_close(db); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值