geekdoc-python-zh/docs/pythoncentral/introduction-to-sqlite-in-p...

8.6 KiB
Raw Permalink Blame History

Python 中的 SQLite 简介

原文:https://www.pythoncentral.io/introduction-to-sqlite-in-python/

SQLite3 是一个非常容易使用的数据库引擎。它是独立的、无服务器的、零配置的和事务性的。它非常快速和轻量级并且整个数据库存储在单个磁盘文件中。它在许多应用中被用作内部数据存储。Python 标准库包括一个名为“sqlite3”的模块用于处理该数据库。这个模块是一个符合 DB-API 2.0 规范的 SQL 接口。

使用 Python 的 SQLite 模块

要使用 SQLite3 模块,我们需要在 python 脚本中添加一条 import 语句:


import sqlite3

将 SQLite 连接到数据库

我们使用函数sqlite3.connect来连接数据库。我们可以使用参数“:memory:”在 RAM 中创建一个临时 DB或者传递一个文件名来打开或创建它。


# Create a database in RAM

db = sqlite3.connect(':memory:')

# Creates or opens a file called mydb with a SQLite3 DB

db = sqlite3.connect('data/mydb')

当我们使用完数据库后,我们需要关闭连接:


db.close()

创建(CREATE)和删除(DROP)表格

为了对数据库进行任何操作,我们需要获得一个游标对象,并将 SQL 语句传递给游标对象来执行它们。最后,提交变更是必要的。我们将创建一个包含姓名、电话、电子邮件和密码列的用户表。


# Get a cursor object

cursor = db.cursor()

cursor.execute('''

CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT,

phone TEXT, email TEXT unique, password TEXT)

''')

db.commit()

要删除表格:


# Get a cursor object

cursor = db.cursor()

cursor.execute('''DROP TABLE users''')

db.commit()

请注意,提交函数是在 db 对象上调用的,而不是在游标对象上。如果我们输入cursor.commit,我们将得到AttributeError: 'sqlite3.Cursor' object has no attribute 'commit'

将数据插入数据库

为了插入数据,我们使用光标来执行查询。如果需要 Python 变量的值,建议使用“?”占位符。不要使用字符串操作或连接来进行查询,因为非常不安全。在本例中,我们将在数据库中插入两个用户,他们的信息存储在 python 变量中。


cursor = db.cursor()

name1 = 'Andres'

phone1 = '3366858'

email1 = 'user@example.com'

# A very secure password

password1 = '12345'
name 2 = ' John '
phone 2 = ' 5557241 '
email 2 = ' John doe @ example . com '
password 2 = ' abcdef '
# Insert user 1
cursor . execute(' ' ' Insert INTO users(namephoneemailpassword) 
 VALUES(,?,?,?)“”,(姓名 1电话 1电子邮件 1密码 1)) 
打印('插入第一个用户')
# Insert user 2
cursor . execute(' ' ' Insert INTO users(namephoneemailpassword) 
 VALUES(,?,?,?)“”,(姓名 2电话 2电子邮件 2密码 2)) 
打印('插入第二个用户')
db.commit() 

Python 变量的值在元组内部传递。另一种方法是使用“:keyname”占位符传递字典:


cursor.execute('''INSERT INTO users(name, phone, email, password)

VALUES(:name,:phone, :email, :password)''',

{'name':name1, 'phone':phone1, 'email':email1, 'password':password1})

如果需要插入几个用户使用executemany和一个带有元组的列表:


users = [(name1,phone1, email1, password1),

(name2,phone2, email2, password2),

(name3,phone3, email3, password3)]

cursor.executemany(''' INSERT INTO users(name, phone, email, password) VALUES(?,?,?,?)''', users)

db.commit()

如果您需要获得刚刚插入的行的 id请使用lastrowid:


id = cursor.lastrowid

print('Last row id: %d' % id)

用 SQLite 检索数据(选择)

要检索数据,对 cursor 对象执行查询,然后使用fetchone()检索单个行,或者使用fetchall()检索所有行。


cursor.execute('''SELECT name, email, phone FROM users''')

user1 = cursor.fetchone() #retrieve the first row

print(user1[0]) #Print the first column retrieved(user's name)

all_rows = cursor.fetchall()

for row in all_rows:

# row[0] returns the first column in the query (name), row[1] returns email column.

print('{0} : {1}, {2}'.format(row[0], row[1], row[2]))

光标对象作为迭代器工作,自动调用fetchall():


cursor.execute('''SELECT name, email, phone FROM users''')

for row in cursor:

# row[0] returns the first column in the query (name), row[1] returns email column.

print('{0} : {1}, {2}'.format(row[0], row[1], row[2]))

要使用条件检索数据,请再次使用“?”占位符:


user_id = 3

cursor.execute('''SELECT name, email, phone FROM users WHERE id=?''', (user_id,))

user = cursor.fetchone()

更新(UPDATE)和删除(DELETE)数据

更新或删除数据的过程与插入数据的过程相同:


# Update user with id 1

newphone = '3113093164'

userid = 1

cursor.execute('''UPDATE users SET phone = ? WHERE id = ? ''',

(newphone, userid))
#删除 id 为 2
Delete _ userid = 2
cursor . execute(' ' '从 id ='的用户中删除''(删除用户标识))
db.commit() 

使用 SQLite 交易

事务是数据库系统的一个有用属性。它确保了数据库的原子性。使用commit保存更改:


cursor.execute('''UPDATE users SET phone = ? WHERE id = ? ''',

(newphone, userid))

db.commit() #Commit the change

或者rollback回滚自上次调用commit以来对数据库的任何更改:


cursor.execute('''UPDATE users SET phone = ? WHERE id = ? ''',

(newphone, userid))

# The user's phone is not updated

db.rollback()

请记住总是调用commit来保存更改。如果您使用close关闭连接或者与文件的连接丢失(可能程序意外结束),未提交的更改将会丢失。

SQLite 数据库异常

最佳实践是始终用 try 子句或上下文管理器围绕数据库操作:


import sqlite3 #Import the SQLite3 module

try:

# Creates or opens a file called mydb with a SQLite3 DB

db = sqlite3.connect('data/mydb')

# Get a cursor object

cursor = db.cursor()

# Check if table users does not exist and create it

cursor.execute('''CREATE TABLE IF NOT EXISTS

users(id INTEGER PRIMARY KEY, name TEXT, phone TEXT, email TEXT unique, password TEXT)''')

# Commit the change

db.commit()

# Catch the exception

except Exception as e:

# Roll back any change if something goes wrong

db.rollback()

raise e

finally:

# Close the db connection

db.close()

在这个例子中,我们使用了 try/except/finally 子句来捕捉代码中的任何异常。finally关键字非常重要,因为它总是正确地关闭数据库连接。请参考这篇文章,了解更多关于例外的信息。请查看:


# Catch the exception

except Exception as e:

raise e

这被称为一个无所不包的子句,这里只是作为一个例子,在实际应用中你应该捕捉一个特定的异常,如IntegrityErrorDatabaseError,更多信息请参考 DB-API 2.0 异常

我们可以使用连接对象作为上下文管理器来自动提交或回滚事务:


name1 = 'Andres'

phone1 = '3366858'

email1 = 'user@example.com'

# A very secure password

password1 = '12345'
try:
with db:
db . execute(' ' ' INSERT INTO users(namephoneemailpassword) 
 VALUES(,?,?,?)“”,(姓名 1电话 1电子邮件 1密码 1)) 
除了 sqlite3IntegrityError: 
打印('记录已经存在')
最后:
 db.close() 

在上面的例子中,如果 insert 语句引发了一个异常,事务将被回滚并打印消息;否则事务将被提交。请注意,我们在db对象上调用execute,而不是cursor对象。

SQLite 行工厂和数据类型

下表显示了 SQLite 数据类型和 Python 数据类型之间的关系:

  • None类型转换为NULL
  • int类型转换为INTEGER
  • float类型转换为REAL
  • str类型转换为TEXT
  • bytes类型转换为BLOB

行工厂类sqlite3.Row用于通过名称而不是索引来访问查询的列: 【python】 db = sqlite3 . connect(' data/mydb ') db . row _ factory = sqlite3。row cursor = db . cursor() cursor . execute(' ' '从用户中选择姓名、电子邮件、电话' ') 对于游标中的行:

row['name']返回查询中的姓名列row['email']返回电子邮件列。

打印(' {0} : {1}{2} '。格式(行['姓名'],行['电子邮件'],行['电话']) db . close()