IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 【Python】SQLite3获取新插入的记录ID及ROWID探究 -> 正文阅读

[大数据]【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?语句的支持。

代码如下:

id = 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?列值。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:25:14  更:2022-05-05 11:29:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:31:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码