【Python】SQLite3获取新插入的记录ID及ROWID探究

sqlite是一个非常好用的轻量级数据库,并且python自带操作sqlite的函数库,开箱即用,对新手特别友好。

1. 傻瓜式调用

Python官方API中,sqlite3.Cursor对象有 lastrowid 属性,使用 cursor.lastrowid 即可得到新插入的数据记录的ID值。

lastrowid

This read-only attribute provides the row id of the last inserted row. It is only updated after successful INSERT or REPLACE statements using the execute() method. For other statements, after executemany() or executescript(), or if the insertion failed, the value of lastrowid is left unchanged. The initial value of lastrowid is None.

Note

Inserts into WITHOUT ROWID tables are not recorded.

Changed in version 3.6: Added support for the REPLACE statement.

翻译:

lastrowid

该属性只读,提供最后插入的行记录的row id。它只有在使用 execute() 方法成功 insert 和 replace 时才会被更新。

使用 executemany() 和 executescript() 方法时 或者插入操作失败时, lastrowid 的值不会变化。

lastrowid 初始值是 None。

注意:

在没有 ROWID 的数据库表执行插入,lastrowid不会记录值。

版本3.6变化:增加对 replace 语句的支持。

代码如下:

# Python3
# -*- coding: utf-8 -*-
import sqlite3

con = sqlite3.connect(":memory:")	# 表示在内存中创建的数据库文件,运行完数据即丢失
cur = con.cursor()

# id 自增
cur.execute("create table t_haha(id INTEGER PRIMARY KEY AUTOINCREMENT,name text, age INTEGER)")

# 第1条数据
data = ("Tom",18)
cur.execute("insert into t_haha(name,age) values (?,?)", data)

theid = cur.lastrowid

2. 深入研究

仔细看说明,可以发现官方手册中说的是 返回新插入记录的 row id,而不是我们自定义的主键id。

而这个 row id是何方神圣呢?

2.1 row id是什么

 默认情况下,所有的SQLite表每一行都有一个特殊的列,通常被称为 rowid,它是每个 表内代表每个行的唯一标识。

如果某个建表语句 create table后附带了 without rowid ,则该表的 rowid 特殊列就会被删除,这个新建的表就是个 WITHOUT ROWID table。

[译自官方此文]

也就是说一般的SQLite的每个表都带有 rowid 列。

2.2 rowid table

注意:下文中的 rowid 和 rowid table 都是专有名词,具有特定的含义,指代特定的一类东西。

我们看看 SQLite 官方网站对 rowid table 的介绍,节选翻译自官方网站的此文

rowid table定义:

  • 不是 virtual table(和视图有点像的东西)
  • 不是 WITHOUT ROWID table

大部分的典型的SQLite数据库表都是 rowid table。

Rowid table 一般有以下特征:它们都有唯一的(unique), 非空的(not-NULL), 带有符号的 64位整型(signed 64-bit integer) rowid,用来在 B-tree存储引擎中作为key索引数据。

变形(Quirks)

  • rowid table 的 PRIMARY KEY 通常并不是用来在B-Tree中索引数据那种意义上的主键。(博主注:说人话,就是说 在SQLite内部B-Tree中,并不是用 PRIMARY KEY 来索引该数据记录的)。这条规则的例外就是,当 rowid table 声明了一个 INTEGER PRIMARY KEY。在这种情况下,这个 INTEGER PRIMARY KEY 就变成了 rowid 的别称
  • rowid table 真正的主键(primary key)是 rowid。(主键(primary key)的值通常用来在内部B-Tree存储中查找指定行的key)。
  • rowid table 的 rowid 可以使用 "rowid"或"oid"或“_rowid_”中的任一个名称作为列名来访问、读写。有一种例外,如果某个表在创建时占用了那些特殊的列名,那么这些特殊的列名就代表声明时的含义,而不是指代 rowid 了。
  • 通过 rowid 获取数据库记录是经过高度优化,速度很快。
  •  rowid 没有被  INTEGER PRIMARY KEY 代替,那么它不是持久的,可能会被更改。特别是 VACUUM命令会改变那些没有声明 INTEGER PRIMARY KEY 的表的rowid。所以,应用软件不建议直接访问 rowid,而是应该用一个 INTEGER PRIMARY KEY 列来代替rowid

总结一下,就是说:

1. 创建表时,主键要创建为 INTEGER PRIMARY KEY,其实我觉得最好再加上自增 AUTOINCREMENT ,这样最简单最完美。

2. 带有 INTEGER PRIMARY KEY 列的SQLite 数据库表,其 rowid 就是 该INTEGER PRIMARY KEY 列。所以,前面 使用 cur.lastrowid 得到就是我们的ID值了。

3. 创建表SQL语句应该这样:

create table t_haha(id INTEGER PRIMARY KEY AUTOINCREMENT,name text, age INTEGER)

这样这个表 t_haha 的id 列就代表原始的 rowid了。

注意:INTEGER PRIMARY KEY  不要写成了 int primary key。大小写无所谓,但是 integer 不要写成了 int,因为 int 不是 sqlite 的基本数据类型。

3. 代码

# Python3
# -*- coding: utf-8 -*-
import sqlite3

con = sqlite3.connect(":memory:")	# 表示在内存中创建的数据库文件,运行完数据即丢失
cur = con.cursor()
# id 自增
cur.execute("create table t_haha(id INTEGER PRIMARY KEY AUTOINCREMENT,name text, age INTEGER)")

# 第1条数据
data = ("Tom",18)
cur.execute("insert into t_haha(name,age) values (?,?)", data)

# 第2条数据
data = ("Jerry",22)
cur.execute("insert into t_haha(name,age) values (?,?)", data)

# 第3条数据
data = ("Lily",25)
cur.execute("insert into t_haha(name,age) values (?,?)", data)

# 打印全部数据
cur.execute("select * from t_haha")
print(cur.fetchall())
print("===insert 3 data, and last row id is", cur.lastrowid)

# 删除第1条 
cur.execute("delete from t_haha where id = 1")

# 打印全部数据
cur.execute("select * from t_haha")
print(cur.fetchall())
print("===delete the first row")

# 再插入1条数据,此时id自动递增,插入后id应该为4
data = ("Peter",100)
cur.execute("insert into t_haha(name,age) values (?,?)", data)

# 验证下 lastrowid 是否严格和自增的id一致
cur.execute("select * from t_haha")
print(cur.fetchall())
print("===last row id:",cur.lastrowid)

con.close()
con.close()

程序输出如下:

表明 cur.lastrowid 值其实就是我们的 id 列值。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qilei2010

送我一张彩票中了平分

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值