~ubuntu-branches/debian/sid/sqlalchemy/sid

« back to all changes in this revision

Viewing changes to doc/_sources/core/constraints.txt

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski
  • Date: 2014-06-27 20:17:13 UTC
  • mfrom: (1.4.28)
  • Revision ID: package-import@ubuntu.com-20140627201713-g6p1kq8q1qenztrv
Tags: 0.9.6-1
* New upstream release
* Remove Python 3.X build tag files, thanks to Matthias Urlichs for the
  patch (closes: #747852)
* python-fdb isn't in the Debian archive yet so default dialect for firebird://
  URLs is changed to obsolete kinterbasdb, thanks to Russell Stuart for the
  patch (closes: #752145)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
.. _metadata_constraints_toplevel:
2
 
.. _metadata_constraints:
3
 
 
4
 
.. module:: sqlalchemy.schema
5
 
 
6
 
=================================
7
 
Defining Constraints and Indexes
8
 
=================================
9
 
 
10
 
.. _metadata_foreignkeys:
11
 
 
12
 
This section will discuss SQL :term:`constraints` and indexes.  In SQLAlchemy
13
 
the key classes include :class:`.ForeignKeyConstraint` and :class:`.Index`.
14
 
 
15
 
Defining Foreign Keys
16
 
---------------------
17
 
 
18
 
A *foreign key* in SQL is a table-level construct that constrains one or more
19
 
columns in that table to only allow values that are present in a different set
20
 
of columns, typically but not always located on a different table. We call the
21
 
columns which are constrained the *foreign key* columns and the columns which
22
 
they are constrained towards the *referenced* columns. The referenced columns
23
 
almost always define the primary key for their owning table, though there are
24
 
exceptions to this. The foreign key is the "joint" that connects together
25
 
pairs of rows which have a relationship with each other, and SQLAlchemy
26
 
assigns very deep importance to this concept in virtually every area of its
27
 
operation.
28
 
 
29
 
In SQLAlchemy as well as in DDL, foreign key constraints can be defined as
30
 
additional attributes within the table clause, or for single-column foreign
31
 
keys they may optionally be specified within the definition of a single
32
 
column. The single column foreign key is more common, and at the column level
33
 
is specified by constructing a :class:`~sqlalchemy.schema.ForeignKey` object
34
 
as an argument to a :class:`~sqlalchemy.schema.Column` object::
35
 
 
36
 
    user_preference = Table('user_preference', metadata,
37
 
        Column('pref_id', Integer, primary_key=True),
38
 
        Column('user_id', Integer, ForeignKey("user.user_id"), nullable=False),
39
 
        Column('pref_name', String(40), nullable=False),
40
 
        Column('pref_value', String(100))
41
 
    )
42
 
 
43
 
Above, we define a new table ``user_preference`` for which each row must
44
 
contain a value in the ``user_id`` column that also exists in the ``user``
45
 
table's ``user_id`` column.
46
 
 
47
 
The argument to :class:`~sqlalchemy.schema.ForeignKey` is most commonly a
48
 
string of the form *<tablename>.<columnname>*, or for a table in a remote
49
 
schema or "owner" of the form *<schemaname>.<tablename>.<columnname>*. It may
50
 
also be an actual :class:`~sqlalchemy.schema.Column` object, which as we'll
51
 
see later is accessed from an existing :class:`~sqlalchemy.schema.Table`
52
 
object via its ``c`` collection::
53
 
 
54
 
    ForeignKey(user.c.user_id)
55
 
 
56
 
The advantage to using a string is that the in-python linkage between ``user``
57
 
and ``user_preference`` is resolved only when first needed, so that table
58
 
objects can be easily spread across multiple modules and defined in any order.
59
 
 
60
 
Foreign keys may also be defined at the table level, using the
61
 
:class:`~sqlalchemy.schema.ForeignKeyConstraint` object. This object can
62
 
describe a single- or multi-column foreign key. A multi-column foreign key is
63
 
known as a *composite* foreign key, and almost always references a table that
64
 
has a composite primary key. Below we define a table ``invoice`` which has a
65
 
composite primary key::
66
 
 
67
 
    invoice = Table('invoice', metadata,
68
 
        Column('invoice_id', Integer, primary_key=True),
69
 
        Column('ref_num', Integer, primary_key=True),
70
 
        Column('description', String(60), nullable=False)
71
 
    )
72
 
 
73
 
And then a table ``invoice_item`` with a composite foreign key referencing
74
 
``invoice``::
75
 
 
76
 
    invoice_item = Table('invoice_item', metadata,
77
 
        Column('item_id', Integer, primary_key=True),
78
 
        Column('item_name', String(60), nullable=False),
79
 
        Column('invoice_id', Integer, nullable=False),
80
 
        Column('ref_num', Integer, nullable=False),
81
 
        ForeignKeyConstraint(['invoice_id', 'ref_num'], ['invoice.invoice_id', 'invoice.ref_num'])
82
 
    )
83
 
 
84
 
It's important to note that the
85
 
:class:`~sqlalchemy.schema.ForeignKeyConstraint` is the only way to define a
86
 
composite foreign key. While we could also have placed individual
87
 
:class:`~sqlalchemy.schema.ForeignKey` objects on both the
88
 
``invoice_item.invoice_id`` and ``invoice_item.ref_num`` columns, SQLAlchemy
89
 
would not be aware that these two values should be paired together - it would
90
 
be two individual foreign key constraints instead of a single composite
91
 
foreign key referencing two columns.
92
 
 
93
 
.. _use_alter:
94
 
 
95
 
Creating/Dropping Foreign Key Constraints via ALTER
96
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97
 
 
98
 
In all the above examples, the :class:`~sqlalchemy.schema.ForeignKey` object
99
 
causes the "REFERENCES" keyword to be added inline to a column definition
100
 
within a "CREATE TABLE" statement when
101
 
:func:`~sqlalchemy.schema.MetaData.create_all` is issued, and
102
 
:class:`~sqlalchemy.schema.ForeignKeyConstraint` invokes the "CONSTRAINT"
103
 
keyword inline with "CREATE TABLE". There are some cases where this is
104
 
undesireable, particularly when two tables reference each other mutually, each
105
 
with a foreign key referencing the other. In such a situation at least one of
106
 
the foreign key constraints must be generated after both tables have been
107
 
built. To support such a scheme, :class:`~sqlalchemy.schema.ForeignKey` and
108
 
:class:`~sqlalchemy.schema.ForeignKeyConstraint` offer the flag
109
 
``use_alter=True``. When using this flag, the constraint will be generated
110
 
using a definition similar to "ALTER TABLE <tablename> ADD CONSTRAINT <name>
111
 
...". Since a name is required, the ``name`` attribute must also be specified.
112
 
For example::
113
 
 
114
 
    node = Table('node', meta,
115
 
        Column('node_id', Integer, primary_key=True),
116
 
        Column('primary_element', Integer,
117
 
            ForeignKey('element.element_id', use_alter=True, name='fk_node_element_id')
118
 
        )
119
 
    )
120
 
 
121
 
    element = Table('element', meta,
122
 
        Column('element_id', Integer, primary_key=True),
123
 
        Column('parent_node_id', Integer),
124
 
        ForeignKeyConstraint(
125
 
            ['parent_node_id'],
126
 
            ['node.node_id'],
127
 
            use_alter=True,
128
 
            name='fk_element_parent_node_id'
129
 
        )
130
 
    )
131
 
 
132
 
.. _on_update_on_delete:
133
 
 
134
 
ON UPDATE and ON DELETE
135
 
~~~~~~~~~~~~~~~~~~~~~~~
136
 
 
137
 
Most databases support *cascading* of foreign key values, that is the when a
138
 
parent row is updated the new value is placed in child rows, or when the
139
 
parent row is deleted all corresponding child rows are set to null or deleted.
140
 
In data definition language these are specified using phrases like "ON UPDATE
141
 
CASCADE", "ON DELETE CASCADE", and "ON DELETE SET NULL", corresponding to
142
 
foreign key constraints. The phrase after "ON UPDATE" or "ON DELETE" may also
143
 
other allow other phrases that are specific to the database in use. The
144
 
:class:`~sqlalchemy.schema.ForeignKey` and
145
 
:class:`~sqlalchemy.schema.ForeignKeyConstraint` objects support the
146
 
generation of this clause via the ``onupdate`` and ``ondelete`` keyword
147
 
arguments. The value is any string which will be output after the appropriate
148
 
"ON UPDATE" or "ON DELETE" phrase::
149
 
 
150
 
    child = Table('child', meta,
151
 
        Column('id', Integer,
152
 
                ForeignKey('parent.id', onupdate="CASCADE", ondelete="CASCADE"),
153
 
                primary_key=True
154
 
        )
155
 
    )
156
 
 
157
 
    composite = Table('composite', meta,
158
 
        Column('id', Integer, primary_key=True),
159
 
        Column('rev_id', Integer),
160
 
        Column('note_id', Integer),
161
 
        ForeignKeyConstraint(
162
 
                    ['rev_id', 'note_id'],
163
 
                    ['revisions.id', 'revisions.note_id'],
164
 
                    onupdate="CASCADE", ondelete="SET NULL"
165
 
        )
166
 
    )
167
 
 
168
 
Note that these clauses are not supported on SQLite, and require ``InnoDB``
169
 
tables when used with MySQL. They may also not be supported on other
170
 
databases.
171
 
 
172
 
 
173
 
UNIQUE Constraint
174
 
-----------------
175
 
 
176
 
Unique constraints can be created anonymously on a single column using the
177
 
``unique`` keyword on :class:`~sqlalchemy.schema.Column`. Explicitly named
178
 
unique constraints and/or those with multiple columns are created via the
179
 
:class:`~sqlalchemy.schema.UniqueConstraint` table-level construct.
180
 
 
181
 
.. sourcecode:: python+sql
182
 
 
183
 
    from sqlalchemy import UniqueConstraint
184
 
 
185
 
    meta = MetaData()
186
 
    mytable = Table('mytable', meta,
187
 
 
188
 
        # per-column anonymous unique constraint
189
 
        Column('col1', Integer, unique=True),
190
 
 
191
 
        Column('col2', Integer),
192
 
        Column('col3', Integer),
193
 
 
194
 
        # explicit/composite unique constraint.  'name' is optional.
195
 
        UniqueConstraint('col2', 'col3', name='uix_1')
196
 
        )
197
 
 
198
 
CHECK Constraint
199
 
----------------
200
 
 
201
 
Check constraints can be named or unnamed and can be created at the Column or
202
 
Table level, using the :class:`~sqlalchemy.schema.CheckConstraint` construct.
203
 
The text of the check constraint is passed directly through to the database,
204
 
so there is limited "database independent" behavior. Column level check
205
 
constraints generally should only refer to the column to which they are
206
 
placed, while table level constraints can refer to any columns in the table.
207
 
 
208
 
Note that some databases do not actively support check constraints such as
209
 
MySQL.
210
 
 
211
 
.. sourcecode:: python+sql
212
 
 
213
 
    from sqlalchemy import CheckConstraint
214
 
 
215
 
    meta = MetaData()
216
 
    mytable = Table('mytable', meta,
217
 
 
218
 
        # per-column CHECK constraint
219
 
        Column('col1', Integer, CheckConstraint('col1>5')),
220
 
 
221
 
        Column('col2', Integer),
222
 
        Column('col3', Integer),
223
 
 
224
 
        # table level CHECK constraint.  'name' is optional.
225
 
        CheckConstraint('col2 > col3 + 5', name='check1')
226
 
        )
227
 
 
228
 
    {sql}mytable.create(engine)
229
 
    CREATE TABLE mytable (
230
 
        col1 INTEGER  CHECK (col1>5),
231
 
        col2 INTEGER,
232
 
        col3 INTEGER,
233
 
        CONSTRAINT check1  CHECK (col2 > col3 + 5)
234
 
    ){stop}
235
 
 
236
 
PRIMARY KEY Constraint
237
 
----------------------
238
 
 
239
 
The primary key constraint of any :class:`.Table` object is implicitly
240
 
present, based on the :class:`.Column` objects that are marked with the
241
 
:paramref:`.Column.primary_key` flag.   The :class:`.PrimaryKeyConstraint`
242
 
object provides explicit access to this constraint, which includes the
243
 
option of being configured directly::
244
 
 
245
 
    from sqlalchemy import PrimaryKeyConstraint
246
 
 
247
 
    my_table = Table('mytable', metadata,
248
 
                Column('id', Integer),
249
 
                Column('version_id', Integer),
250
 
                Column('data', String(50)),
251
 
                PrimaryKeyConstraint('id', 'version_id', name='mytable_pk')
252
 
            )
253
 
 
254
 
.. seealso::
255
 
 
256
 
    :class:`.PrimaryKeyConstraint` - detailed API documentation.
257
 
 
258
 
Setting up Constraints when using the Declarative ORM Extension
259
 
----------------------------------------------------------------
260
 
 
261
 
The :class:`.Table` is the SQLAlchemy Core construct that allows one to define
262
 
table metadata, which among other things can be used by the SQLAlchemy ORM
263
 
as a target to map a class.  The :ref:`Declarative <declarative_toplevel>`
264
 
extension allows the :class:`.Table` object to be created automatically, given
265
 
the contents of the table primarily as a mapping of :class:`.Column` objects.
266
 
 
267
 
To apply table-level constraint objects such as :class:`.ForeignKeyConstraint`
268
 
to a table defined using Declarative, use the ``__table_args__`` attribute,
269
 
described at :ref:`declarative_table_args`.
270
 
 
271
 
.. _constraint_naming_conventions:
272
 
 
273
 
Configuring Constraint Naming Conventions
274
 
-----------------------------------------
275
 
 
276
 
Relational databases typically assign explicit names to all constraints and
277
 
indexes.  In the common case that a table is created using ``CREATE TABLE``
278
 
where constraints such as CHECK, UNIQUE, and PRIMARY KEY constraints are
279
 
produced inline with the table definition, the database usually has a system
280
 
in place in which names are automatically assigned to these constraints, if
281
 
a name is not otherwise specified.  When an existing database table is altered
282
 
in a database using a command such as ``ALTER TABLE``, this command typically
283
 
needs to specify expicit names for new constraints as well as be able to
284
 
specify the name of an existing constraint that is to be dropped or modified.
285
 
 
286
 
Constraints can be named explicitly using the :paramref:`.Constraint.name` parameter,
287
 
and for indexes the :paramref:`.Index.name` parameter.  However, in the
288
 
case of constraints this parameter is optional.  There are also the use
289
 
cases of using the :paramref:`.Column.unique` and :paramref:`.Column.index`
290
 
parameters which create :class:`.UniqueConstraint` and :class:`.Index` objects
291
 
without an explicit name being specified.
292
 
 
293
 
The use case of alteration of existing tables and constraints can be handled
294
 
by schema migration tools such as `Alembic <http://http://alembic.readthedocs.org/>`_.
295
 
However, neither Alembic nor SQLAlchemy currently create names for constraint
296
 
objects where the name is otherwise unspecified, leading to the case where
297
 
being able to alter existing constraints means that one must reverse-engineer
298
 
the naming system used by the relational database to auto-assign names,
299
 
or that care must be taken to ensure that all constraints are named.
300
 
 
301
 
In contrast to having to assign explicit names to all :class:`.Constraint`
302
 
and :class:`.Index` objects, automated naming schemes can be constructed
303
 
using events.  This approach has the advantage that constraints will get
304
 
a consistent naming scheme without the need for explicit name parameters
305
 
throughout the code, and also that the convention takes place just as well
306
 
for those constraints and indexes produced by the :paramref:`.Column.unique`
307
 
and :paramref:`.Column.index` parameters.  As of SQLAlchemy 0.9.2 this
308
 
event-based approach is included, and can be configured using the argument
309
 
:paramref:`.MetaData.naming_convention`.
310
 
 
311
 
:paramref:`.MetaData.naming_convention` refers to a dictionary which accepts
312
 
the :class:`.Index` class or individual :class:`.Constraint` classes as keys,
313
 
and Python string templates as values.   It also accepts a series of
314
 
string-codes as alternative keys, ``"fk"``, ``"pk"``,
315
 
``"ix"``, ``"ck"``, ``"uq"`` for foreign key, primary key, index,
316
 
check, and unique constraint, respectively.  The string templates in this
317
 
dictionary are used whenever a constraint or index is associated with this
318
 
:class:`.MetaData` object that does not have an existing name given (including
319
 
one exception case where an existing name can be further embellished).
320
 
 
321
 
An example naming convention that suits basic cases is as follows::
322
 
 
323
 
    convention = {
324
 
      "ix": 'ix_%(column_0_label)s',
325
 
      "uq": "uq_%(table_name)s_%(column_0_name)s",
326
 
      "ck": "ck_%(table_name)s_%(constraint_name)s",
327
 
      "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
328
 
      "pk": "pk_%(table_name)s"
329
 
    }
330
 
 
331
 
    metadata = MetaData(naming_convention=convention)
332
 
 
333
 
The above convention will establish names for all constraints within
334
 
the target :class:`.MetaData` collection.
335
 
For example, we can observe the name produced when we create an unnamed
336
 
:class:`.UniqueConstraint`::
337
 
 
338
 
    >>> user_table = Table('user', metadata,
339
 
    ...                 Column('id', Integer, primary_key=True),
340
 
    ...                 Column('name', String(30), nullable=False),
341
 
    ...                 UniqueConstraint('name')
342
 
    ... )
343
 
    >>> list(user_table.constraints)[1].name
344
 
    'uq_user_name'
345
 
 
346
 
This same feature takes effect even if we just use the :paramref:`.Column.unique`
347
 
flag::
348
 
 
349
 
    >>> user_table = Table('user', metadata,
350
 
    ...                  Column('id', Integer, primary_key=True),
351
 
    ...                  Column('name', String(30), nullable=False, unique=True)
352
 
    ...     )
353
 
    >>> list(user_table.constraints)[1].name
354
 
    'uq_user_name'
355
 
 
356
 
A key advantage to the naming convention approach is that the names are established
357
 
at Python construction time, rather than at DDL emit time.  The effect this has
358
 
when using Alembic's ``--autogenerate`` feature is that the naming convention
359
 
will be explicit when a new migration script is generated::
360
 
 
361
 
    def upgrade():
362
 
        op.create_unique_constraint("uq_user_name", "user", ["name"])
363
 
 
364
 
The above ``"uq_user_name"`` string was copied from the :class:`.UniqueConstraint`
365
 
object that ``--autogenerate`` located in our metadata.
366
 
 
367
 
The default value for :paramref:`.MetaData.naming_convention` handles
368
 
the long-standing SQLAlchemy behavior of assigning a name to a :class:`.Index`
369
 
object that is created using the :paramref:`.Column.index` parameter::
370
 
 
371
 
    >>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
372
 
    >>> DEFAULT_NAMING_CONVENTION
373
 
    immutabledict({'ix': 'ix_%(column_0_label)s'})
374
 
 
375
 
The tokens available include ``%(table_name)s``,
376
 
``%(referred_table_name)s``, ``%(column_0_name)s``, ``%(column_0_label)s``,
377
 
``%(column_0_key)s``,  ``%(referred_column_0_name)s``, and ``%(constraint_name)s``;
378
 
the documentation for :paramref:`.MetaData.naming_convention` describes each
379
 
individually.  New tokens can also be added, by specifying an additional
380
 
token and a callable within the naming_convention dictionary.  For example,
381
 
if we wanted to name our foreign key constraints using a GUID scheme,
382
 
we could do that as follows::
383
 
 
384
 
    import uuid
385
 
 
386
 
    def fk_guid(constraint, table):
387
 
        str_tokens = [
388
 
            table.name,
389
 
        ] + [
390
 
            element.parent.name for element in constraint.elements
391
 
        ] + [
392
 
            element.target_fullname for element in constraint.elements
393
 
        ]
394
 
        guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode('ascii'))
395
 
        return str(guid)
396
 
 
397
 
    convention = {
398
 
        "fk_guid": fk_guid,
399
 
        "ix": 'ix_%(column_0_label)s',
400
 
        "fk": "fk_%(fk_guid)s",
401
 
    }
402
 
 
403
 
Above, when we create a new :class:`.ForeignKeyConstraint`, we will get a
404
 
name as follows::
405
 
 
406
 
    >>> metadata = MetaData(naming_convention=convention)
407
 
 
408
 
    >>> user_table = Table('user', metadata,
409
 
    ...         Column('id', Integer, primary_key=True),
410
 
    ...         Column('version', Integer, primary_key=True),
411
 
    ...         Column('data', String(30))
412
 
    ...     )
413
 
    >>> address_table = Table('address', metadata,
414
 
    ...        Column('id', Integer, primary_key=True),
415
 
    ...        Column('user_id', Integer),
416
 
    ...        Column('user_version_id', Integer)
417
 
    ...    )
418
 
    >>> fk = ForeignKeyConstraint(['user_id', 'user_version_id'],
419
 
    ...                ['user.id', 'user.version'])
420
 
    >>> address_table.append_constraint(fk)
421
 
    >>> fk.name
422
 
    fk_0cd51ab5-8d70-56e8-a83c-86661737766d
423
 
 
424
 
.. seealso::
425
 
 
426
 
    :paramref:`.MetaData.naming_convention` - for additional usage details
427
 
    as well as a listing of all avaiable naming components.
428
 
 
429
 
    :ref:`alembic:tutorial_constraint_names` - in the Alembic documentation.
430
 
 
431
 
.. versionadded:: 0.9.2 Added the :paramref:`.MetaData.naming_convention` argument.
432
 
 
433
 
Constraints API
434
 
---------------
435
 
.. autoclass:: Constraint
436
 
    :members:
437
 
 
438
 
.. autoclass:: CheckConstraint
439
 
    :members:
440
 
    :inherited-members:
441
 
 
442
 
.. autoclass:: ColumnCollectionConstraint
443
 
    :members:
444
 
 
445
 
.. autoclass:: ForeignKey
446
 
    :members:
447
 
    :inherited-members:
448
 
 
449
 
 
450
 
.. autoclass:: ForeignKeyConstraint
451
 
    :members:
452
 
    :inherited-members:
453
 
 
454
 
 
455
 
.. autoclass:: PrimaryKeyConstraint
456
 
    :members:
457
 
    :inherited-members:
458
 
 
459
 
 
460
 
.. autoclass:: UniqueConstraint
461
 
    :members:
462
 
    :inherited-members:
463
 
 
464
 
.. autofunction:: sqlalchemy.schema.conv
465
 
 
466
 
.. _schema_indexes:
467
 
 
468
 
Indexes
469
 
-------
470
 
 
471
 
Indexes can be created anonymously (using an auto-generated name ``ix_<column
472
 
label>``) for a single column using the inline ``index`` keyword on
473
 
:class:`~sqlalchemy.schema.Column`, which also modifies the usage of
474
 
``unique`` to apply the uniqueness to the index itself, instead of adding a
475
 
separate UNIQUE constraint. For indexes with specific names or which encompass
476
 
more than one column, use the :class:`~sqlalchemy.schema.Index` construct,
477
 
which requires a name.
478
 
 
479
 
Below we illustrate a :class:`~sqlalchemy.schema.Table` with several
480
 
:class:`~sqlalchemy.schema.Index` objects associated. The DDL for "CREATE
481
 
INDEX" is issued right after the create statements for the table:
482
 
 
483
 
.. sourcecode:: python+sql
484
 
 
485
 
    meta = MetaData()
486
 
    mytable = Table('mytable', meta,
487
 
        # an indexed column, with index "ix_mytable_col1"
488
 
        Column('col1', Integer, index=True),
489
 
 
490
 
        # a uniquely indexed column with index "ix_mytable_col2"
491
 
        Column('col2', Integer, index=True, unique=True),
492
 
 
493
 
        Column('col3', Integer),
494
 
        Column('col4', Integer),
495
 
 
496
 
        Column('col5', Integer),
497
 
        Column('col6', Integer),
498
 
        )
499
 
 
500
 
    # place an index on col3, col4
501
 
    Index('idx_col34', mytable.c.col3, mytable.c.col4)
502
 
 
503
 
    # place a unique index on col5, col6
504
 
    Index('myindex', mytable.c.col5, mytable.c.col6, unique=True)
505
 
 
506
 
    {sql}mytable.create(engine)
507
 
    CREATE TABLE mytable (
508
 
        col1 INTEGER,
509
 
        col2 INTEGER,
510
 
        col3 INTEGER,
511
 
        col4 INTEGER,
512
 
        col5 INTEGER,
513
 
        col6 INTEGER
514
 
    )
515
 
    CREATE INDEX ix_mytable_col1 ON mytable (col1)
516
 
    CREATE UNIQUE INDEX ix_mytable_col2 ON mytable (col2)
517
 
    CREATE UNIQUE INDEX myindex ON mytable (col5, col6)
518
 
    CREATE INDEX idx_col34 ON mytable (col3, col4){stop}
519
 
 
520
 
Note in the example above, the :class:`.Index` construct is created
521
 
externally to the table which it corresponds, using :class:`.Column`
522
 
objects directly.  :class:`.Index` also supports
523
 
"inline" definition inside the :class:`.Table`, using string names to
524
 
identify columns::
525
 
 
526
 
    meta = MetaData()
527
 
    mytable = Table('mytable', meta,
528
 
        Column('col1', Integer),
529
 
 
530
 
        Column('col2', Integer),
531
 
 
532
 
        Column('col3', Integer),
533
 
        Column('col4', Integer),
534
 
 
535
 
        # place an index on col1, col2
536
 
        Index('idx_col12', 'col1', 'col2'),
537
 
 
538
 
        # place a unique index on col3, col4
539
 
        Index('idx_col34', 'col3', 'col4', unique=True)
540
 
    )
541
 
 
542
 
.. versionadded:: 0.7
543
 
    Support of "inline" definition inside the :class:`.Table`
544
 
    for :class:`.Index`\ .
545
 
 
546
 
The :class:`~sqlalchemy.schema.Index` object also supports its own ``create()`` method:
547
 
 
548
 
.. sourcecode:: python+sql
549
 
 
550
 
    i = Index('someindex', mytable.c.col5)
551
 
    {sql}i.create(engine)
552
 
    CREATE INDEX someindex ON mytable (col5){stop}
553
 
 
554
 
.. _schema_indexes_functional:
555
 
 
556
 
Functional Indexes
557
 
~~~~~~~~~~~~~~~~~~~
558
 
 
559
 
:class:`.Index` supports SQL and function expressions, as supported by the
560
 
target backend.  To create an index against a column using a descending
561
 
value, the :meth:`.ColumnElement.desc` modifier may be used::
562
 
 
563
 
    from sqlalchemy import Index
564
 
 
565
 
    Index('someindex', mytable.c.somecol.desc())
566
 
 
567
 
Or with a backend that supports functional indexes such as Postgresql,
568
 
a "case insensitive" index can be created using the ``lower()`` function::
569
 
 
570
 
    from sqlalchemy import func, Index
571
 
 
572
 
    Index('someindex', func.lower(mytable.c.somecol))
573
 
 
574
 
.. versionadded:: 0.8 :class:`.Index` supports SQL expressions and functions
575
 
   as well as plain columns.
576
 
 
577
 
Index API
578
 
---------
579
 
 
580
 
.. autoclass:: Index
581
 
    :members:
582
 
    :inherited-members: