Tutorial\r
========\r
-This tutorial is a "quick start" guide to SQLAlchemy, the Python SQL Toolkit and Object Relational Mapper.\r
-SQLAlchemy provides a lot of functionality to help manage SQL databases, but you don't need much in order to begin doing useful things with it.\r
-\r
-Note that it is not neccessary to read this tutorial; you may wish to skip it and dive into the [main manual][manual] which is more reference-oriented.\r
+This tutorial is a "quick start" guide to SQLAlchemy. You may wish to skip it and dive into the [main manual][manual] which is more reference-oriented.\r
\r
[manual]: rel:howtoread\r
\r
\r
### Installing SQLAlchemy {@name=sqlalchemy}\r
\r
-Installing SQLAlchemy is easy if you have [setuptools][] on your system (if you don't, [install it][install setuptools], it's easy!). Just run this from the command-line:\r
+Installing SQLAlchemy from scratch is most easily achieved with [setuptools][]. ([setuptools installation][install setuptools]). Just run this from the command-line:\r
\r
$ easy_install SQLAlchemy\r
\r
\r
### Installing A Database Manager {@name=dbms}\r
\r
- SQLAlchemy is designed to operate with the [DBAPI][DBAPI] built for a particular database, and includes implementations supporting the most popular ones. If you have one of the [supported database managers][supported dbms], you can proceed to the following section. Otherwise we recommend installing [SQLite][] for starters. SQLite needs very little configuration and is easy to work with.\r
+ SQLAlchemy is designed to operate with a [DBAPI][DBAPI] implementation built for a particular database, and includes support for the most popular databases. If you have one of the [supported database managers][supported dbms], you can proceed to the following section. Otherwise [SQLite][] is an easy to use database to get started with, requiring very little configuration.\r
\r
[DBAPI]: http://www.python.org/doc/peps/pep-0249/\r
\r
To work with SQLite, you'll need:\r
\r
- * SQLite library\r
* [pysqlite][] - Python interface for SQLite\r
+ * SQLite library \r
\r
-If you use Windows, you only have to download and install the compiled [pysqlite binary][pysqlite]. It includes the SQLite library already linked in, so you don't have to install it separately.\r
-\r
-If you use Linux or FreeBSD, you may want to install pysqlite and SQLite from [packages][pysqlite packages] made for your operating system. Or you may install them [from sources][pysqlite].\r
+Note that the SQLite library download is not required with Windows, as the Windows Pysqlite library already includes it linked in. Pysqlite and SQLite can also be installed on Linux or FreeBSD via pre-made [packages][pysqlite packages] or [from sources][pysqlite].\r
\r
[supported dbms]: rel:dbengine_establishing\r
[sqlite]: http://sqlite.org/\r
[pysqlite]: http://pysqlite.org/\r
[pysqlite packages]: http://initd.org/tracker/pysqlite/wiki/PysqlitePackages\r
\r
-Get Going! {@name=getgoing}\r
+Getting Started {@name=gettingstarted}\r
--------------------------\r
\r
### Connecting to the Database\r
>>> from sqlalchemy import *\r
>>> db = create_engine('sqlite://filename=tutorial.db')\r
\r
-Main documentation: [dbengine](rel:dbengine).\r
+Documentation on creating engines is available in [dbengine](rel:dbengine).\r
\r
### Creating a Table {@name=table}\r
\r
-A core philosophy of SQLAlchemy is that tables and domain classes are different beasts. That's why SQLAlchemy doesn't mix them. So let's first work with just tables alone; we construct an object that represents a table:\r
+A core philosophy of SQLAlchemy is that tables and domain classes are different beasts. For this reason, SQLAlchemy provides constructs that represent tables by themselves (known as *table metadata*). So we will begin by constructing table metadata objects and performing SQL operations with them directly, keeping in mind that there is also an Object Relational Mapper (ORM) which does the same thing except via domain models. Let's construct an object that represents a table:\r
\r
>>> users = Table('users', db,\r
... Column('user_id', Integer, primary_key = True),\r
... Column('password', String(80))\r
... )\r
\r
-As you might have guessed, we have just defined a table `users` with 3 columns: `user_id` (which is a primary key column), `user_name` and `password`. Currently it is just an object that may not correspond to an existing table in your database. So let's create the real table! To make it interesting we will ask SQLAlchemy to echo the SQL statements it sends to the database:\r
+As you might have guessed, we have just defined a table named `users` which has three columns: `user_id` (which is a primary key column), `user_name` and `password`. Currently it is just an object that may not correspond to an existing table in your database. To actually create the table, we use the `create()` method. To make it interesting we will have SQLAlchemy to echo the SQL statements it sends to the database:\r
\r
>>> db.echo = True\r
>>> users.create() # doctest:+ELLIPSIS,+NORMALIZE_WHITESPACE\r
>>> list(users.columns)[0].name\r
'user_id'\r
\r
-Main documentation: [metadata](rel:metadata).\r
+Documentation on table metadata is available in [metadata](rel:metadata).\r
\r
-### Filling the Table\r
+### Inserting Rows\r
\r
-So now we have the table. To insert some data, use the `insert()` method to create a query:\r
+Inserting is achieved via the `insert()` method, which defines a *clause object* representing an INSERT statement:\r
\r
>>> i = users.insert()\r
>>> i # doctest:+ELLIPSIS\r
>>> print i\r
INSERT INTO users (user_id, user_name, password) VALUES (?, ?, ?)\r
\r
-Call the `execute()` method of the query object to actually add users:\r
+The `execute()` method of the clause object executes the statement at the database level:\r
\r
>>> for name in ['Tom', 'Dick', 'Harry']: # doctest:+ELLIPSIS\r
... i.execute(user_name = name)\r
>>> i.execute(user_name = 'Mary', password = 'secure') # doctest:+ELLIPSIS\r
<sqlalchemy.engine.ResultProxy instance at 0x...>\r
\r
-SQLAlchemy will bind all literal values into bind parameters, according to the paramstyle of the underlying DBAPI. This allows for better performance, because the database may cache a compiled representation of the statement and reuse upon new executions, substituting the new values. Also, when using bound values, you need not worry about [SQL injection][] attacks.\r
+When constructing clause objects, SQLAlchemy will bind all literal values into bind parameters, according to the paramstyle of the underlying DBAPI. This allows for better performance, as the database may cache a compiled representation of the statement and reuse it for new executions, substituting the new values. Also, when using bound values, you need not worry about [SQL injection][] attacks.\r
\r
[SQL injection]: http://en.wikipedia.org/wiki/SQL_injection\r
\r
-Main documentation: [sql_insert](rel:sql_insert).\r
+Documentation on inserting: [sql_insert](rel:sql_insert).\r
\r
-### Querying the Table\r
+### Constructing Queries\r
\r
-Let's check that the data we have put into `users` table is actually there. The procedure is analogous to the insert example above, except you now call the `select()` function:\r
+Let's check that the data we have put into `users` table is actually there. The procedure is analogous to the insert example above, except you now call the `select()` method off the `users` table:\r
\r
>>> s = users.select()\r
>>> print s\r
>>> r.fetchall()\r
[(2, u'Dick', None), (3, u'Harry', None), (4, u'Mary', u'secure')]\r
\r
-Main documentation: [sql_select](rel:sql_select).\r
+Documentation on selecting: [sql_select](rel:sql_select).\r
\r
### Related Table\r
\r