Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-95271: Improve sqlite3 tutorial wording #95749

Merged
Merged
Changes from 12 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
974022c
gh-95271: Improve sqlite3 tutorial wording
erlend-aasland Aug 6, 2022
f21d777
Fix rest syntax
erlend-aasland Aug 6, 2022
4231b75
Improve count query comment
erlend-aasland Aug 6, 2022
e08ca43
SQL commands => SQL queries
erlend-aasland Aug 6, 2022
f9a5664
Improve transaction control paragraph
erlend-aasland Aug 6, 2022
484f341
Be more to the point
erlend-aasland Aug 6, 2022
ae0969f
Fix ref
erlend-aasland Aug 6, 2022
d1d11f4
Missing 'the'; even more to the point
erlend-aasland Aug 6, 2022
9870036
Be more accurate
erlend-aasland Aug 6, 2022
431dcb5
Remove unneeded comments; the instructions don't need to be reiterated
erlend-aasland Aug 6, 2022
ac7d870
Merge branch 'main' into sqlite-tutorial/improve-wording
erlend-aasland Aug 8, 2022
f4b66ac
Address Ezio's initial review
erlend-aasland Aug 8, 2022
09ac89d
Address second round of reviews from both Ezio and CAM
erlend-aasland Aug 9, 2022
cbfb325
Use Python version history as example database
erlend-aasland Aug 9, 2022
deb199c
move sphinx comment; it creates havoc
erlend-aasland Aug 9, 2022
d54ff8d
Address a new round of reviews from CAM
erlend-aasland Aug 9, 2022
e778012
Update the example, be more explicit
erlend-aasland Aug 10, 2022
e9e1ffa
Address review comments
erlend-aasland Aug 11, 2022
f60e3a2
Missing blank line below Sphinx comment
erlend-aasland Aug 11, 2022
5d03a4e
Address reviews from 2022-08-11
erlend-aasland Aug 12, 2022
3ec75d1
Tone: use second person singular more often
erlend-aasland Aug 12, 2022
84d798f
Adressing the last rounds of comments from CAM, Daniele, and Ezio
erlend-aasland Aug 14, 2022
d09d9f6
you will need to => you need to
erlend-aasland Aug 14, 2022
d6f4775
Address more review comments
erlend-aasland Aug 14, 2022
b46942b
Address CAM's last round of comments; use first person plural
erlend-aasland Aug 15, 2022
4a51e1e
Typos
erlend-aasland Aug 15, 2022
92fa693
Nits and a link
erlend-aasland Aug 15, 2022
d40c2a7
Adjust 'non-existent' example; adjust final query; sort links
erlend-aasland Aug 16, 2022
d2c3968
Rewrite an 'as expected'
erlend-aasland Aug 16, 2022
32a19e9
Fix string format anti-pattern
erlend-aasland Aug 17, 2022
dd38587
Clarify how we verify that the table has been created
Aug 18, 2022
f41be9b
Update Doc/library/sqlite3.rst
Aug 18, 2022
0e0398d
Update Doc/library/sqlite3.rst
Aug 18, 2022
cb41c49
Revert "Update Doc/library/sqlite3.rst"
erlend-aasland Aug 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,51 +52,54 @@ This document includes four main sections:
Tutorial
--------

To use the module, start by creating a :class:`Connection` object that
represents the database. Here the data will be stored in the
:file:`example.db` file::
In this tutorial you will learn the basics of the :mod:`!sqlite3` API
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
by creating an on-disk database :file:`example.db`,
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
and executing SQL queries against it.
A fundamental understanding of database concepts,
like transactions and cursors, is assumed.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

Start by using the :func:`sqlite3.connect` function to
open a database :class:`Connection` to :file:`example.db`;
SQLite will implicitly create the database file :file:`example`
in the current working directory, if it does not exist.
The returned :class:`!Connection` object represents our
connection to the on-disk SQLite database::

import sqlite3
con = sqlite3.connect('example.db')

erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
The special path name ``:memory:`` can be provided to create a temporary
database in RAM.

Once a :class:`Connection` has been established, create a :class:`Cursor` object
and call its :meth:`~Cursor.execute` method to perform SQL commands::
Now, create a :class:`Cursor` object using :meth:`~Connection.cursor`.
ezio-melotti marked this conversation as resolved.
Show resolved Hide resolved
Call its :meth:`~Cursor.execute` method to perform SQL queries::
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

cur = con.cursor()

# Create table
# Create table, then insert a row of data.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
cur.execute('''CREATE TABLE stocks
(date text, trans text, symbol text, qty real, price real)''')

# Insert a row of data
cur.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")

# Save (commit) the changes
con.commit()
The ``INSERT`` statement implicitly opens a transaction
that needs to be committed before changes are saved in the database.
For more details, see the :ref:`sqlite3-controlling-transactions` how-to.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Use the connection object to :meth:`~Connection.commit` the transaction::
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
con.close()
con.commit() # Save the changes.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

The saved data is persistent: it can be reloaded in a subsequent session even
after restarting the Python interpreter::

import sqlite3
con = sqlite3.connect('example.db')
cur = con.cursor()

At this point, our database only contains one row::
Verify that data has been committed and written to disk:
close the connection, open a new connection,
create a new cursor,
then use a ``SELECT`` query to read from the database::
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

>>> con.close()
>>> con = sqlite3.connect('example.db')
>>> cur = con.cursor()
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
>>> res = cur.execute('SELECT count(rowid) FROM stocks')
>>> print(res.fetchone())
(1,)

The result is a one-item :class:`tuple`:
one row, with one column.
Now, let us insert three more rows of data,
Now, insert three more rows of data,
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
using :meth:`~Cursor.executemany`::
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

>>> data = [
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -112,7 +115,7 @@ to bind Python values to SQL statements,
to avoid `SQL injection attacks`_.
See the :ref:`placeholders how-to <sqlite3-placeholders>` for more details.

Then, retrieve the data by iterating over the result of a ``SELECT`` statement::
Now, retrieve the rows by iterating over the result of a ``SELECT`` query::

>>> for row in cur.execute('SELECT * FROM stocks ORDER BY price'):
... print(row)
Expand All @@ -122,6 +125,7 @@ Then, retrieve the data by iterating over the result of a ``SELECT`` statement::
('2006-04-06', 'SELL', 'IBM', 500, 53.0)
('2006-04-05', 'BUY', 'MSFT', 1000, 72.0)

Each row is a five-item :class:`!tuple`.
You've now created an SQLite database using the :mod:`!sqlite3` module.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

.. _SQL injection attacks: https://en.wikipedia.org/wiki/SQL_injection
Expand Down