~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski, Jakub Wilk, Piotr Ożarowski
  • Date: 2013-07-06 20:53:52 UTC
  • mfrom: (1.4.23) (16.1.17 experimental)
  • Revision ID: package-import@ubuntu.com-20130706205352-ryppl1eto3illd79
Tags: 0.8.2-1
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Piotr Ożarowski ]
* New upstream release
* Upload to unstable
* Build depend on python3-all instead of -dev, extensions are not built for
  Python 3.X 

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
=============
51
51
 
52
52
 
53
 
A quick check to verify that we are on at least **version 0.7** of SQLAlchemy:
 
53
A quick check to verify that we are on at least **version 0.8** of SQLAlchemy:
54
54
 
55
55
.. sourcecode:: pycon+sql
56
56
 
57
57
    >>> import sqlalchemy
58
58
    >>> sqlalchemy.__version__ # doctest:+SKIP
59
 
    0.7.0
 
59
    0.8.0
60
60
 
61
61
Connecting
62
62
==========
266
266
What about the ``result`` variable we got when we called ``execute()`` ? As
267
267
the SQLAlchemy :class:`~sqlalchemy.engine.base.Connection` object references a
268
268
DBAPI connection, the result, known as a
269
 
:class:`~sqlalchemy.engine.base.ResultProxy` object, is analogous to the DBAPI
 
269
:class:`~sqlalchemy.engine.result.ResultProxy` object, is analogous to the DBAPI
270
270
cursor object. In the case of an INSERT, we can get important information from
271
271
it, such as the primary key values which were generated from our statement:
272
272
 
304
304
    {opensql}INSERT INTO users (id, name, fullname) VALUES (?, ?, ?)
305
305
    (2, 'wendy', 'Wendy Williams')
306
306
    COMMIT
307
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
307
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
308
308
 
309
 
Above, because we specified all three columns in the the ``execute()`` method,
310
 
the compiled :class:`~sqlalchemy.sql.expression.Insert` included all three
311
 
columns. The :class:`~sqlalchemy.sql.expression.Insert` statement is compiled
 
309
Above, because we specified all three columns in the ``execute()`` method,
 
310
the compiled :class:`~.expression.Insert` included all three
 
311
columns. The :class:`~.expression.Insert` statement is compiled
312
312
at execution time based on the parameters we specified; if we specified fewer
313
 
parameters, the :class:`~sqlalchemy.sql.expression.Insert` would have fewer
 
313
parameters, the :class:`~.expression.Insert` would have fewer
314
314
entries in its VALUES clause.
315
315
 
316
316
To issue many inserts using DBAPI's ``executemany()`` method, we can send in a
328
328
    {opensql}INSERT INTO addresses (user_id, email_address) VALUES (?, ?)
329
329
    ((1, 'jack@yahoo.com'), (1, 'jack@msn.com'), (2, 'www@www.org'), (2, 'wendy@aol.com'))
330
330
    COMMIT
331
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
331
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
332
332
 
333
333
Above, we again relied upon SQLite's automatic generation of primary key
334
334
identifiers for each ``addresses`` row.
363
363
within the COLUMNS clause of the select, and then executing. SQLAlchemy
364
364
expanded the ``users`` table into the set of each of its columns, and also
365
365
generated a FROM clause for us. The result returned is again a
366
 
:class:`~sqlalchemy.engine.base.ResultProxy` object, which acts much like a
 
366
:class:`~sqlalchemy.engine.result.ResultProxy` object, which acts much like a
367
367
DBAPI cursor, including methods such as
368
 
:func:`~sqlalchemy.engine.base.ResultProxy.fetchone` and
369
 
:func:`~sqlalchemy.engine.base.ResultProxy.fetchall`. The easiest way to get
 
368
:func:`~sqlalchemy.engine.result.ResultProxy.fetchone` and
 
369
:func:`~sqlalchemy.engine.result.ResultProxy.fetchall`. The easiest way to get
370
370
rows from it is to just iterate:
371
371
 
372
372
.. sourcecode:: pycon+sql
375
375
    ...     print row
376
376
    (1, u'jack', u'Jack Jones')
377
377
    (2, u'wendy', u'Wendy Williams')
378
 
    (3, u'fred', u'Fred Flintstone')
379
 
    (4, u'mary', u'Mary Contrary')
380
378
 
381
379
Above, we see that printing each row produces a simple tuple-like result. We
382
380
have more options at accessing the data in each row. One very common way is
413
411
    ()
414
412
    {stop}name: jack ; fullname: Jack Jones
415
413
    name: wendy ; fullname: Wendy Williams
416
 
    name: fred ; fullname: Fred Flintstone
417
 
    name: mary ; fullname: Mary Contrary
418
414
 
419
415
Result sets which have pending rows remaining should be explicitly closed
420
416
before discarding. While the cursor and connection resources referenced by the
421
 
:class:`~sqlalchemy.engine.base.ResultProxy` will be respectively closed and
 
417
:class:`~sqlalchemy.engine.result.ResultProxy` will be respectively closed and
422
418
returned to the connection pool when the object is garbage collected, it's
423
419
better to make it explicit as some database APIs are very picky about such
424
420
things:
444
440
    ...     print row
445
441
    (u'jack', u'Jack Jones')
446
442
    (u'wendy', u'Wendy Williams')
447
 
    (u'fred', u'Fred Flintstone')
448
 
    (u'mary', u'Mary Contrary')
449
443
 
450
444
Lets observe something interesting about the FROM clause. Whereas the
451
445
generated statement contains two distinct sections, a "SELECT columns" part
468
462
    (2, u'wendy', u'Wendy Williams', 2, 1, u'jack@msn.com')
469
463
    (2, u'wendy', u'Wendy Williams', 3, 2, u'www@www.org')
470
464
    (2, u'wendy', u'Wendy Williams', 4, 2, u'wendy@aol.com')
471
 
    (3, u'fred', u'Fred Flintstone', 1, 1, u'jack@yahoo.com')
472
 
    (3, u'fred', u'Fred Flintstone', 2, 1, u'jack@msn.com')
473
 
    (3, u'fred', u'Fred Flintstone', 3, 2, u'www@www.org')
474
 
    (3, u'fred', u'Fred Flintstone', 4, 2, u'wendy@aol.com')
475
 
    (4, u'mary', u'Mary Contrary', 1, 1, u'jack@yahoo.com')
476
 
    (4, u'mary', u'Mary Contrary', 2, 1, u'jack@msn.com')
477
 
    (4, u'mary', u'Mary Contrary', 3, 2, u'www@www.org')
478
 
    (4, u'mary', u'Mary Contrary', 4, 2, u'wendy@aol.com')
479
465
 
480
466
It placed **both** tables into the FROM clause. But also, it made a real mess.
481
467
Those who are familiar with SQL joins know that this is a **Cartesian
482
468
product**; each row from the ``users`` table is produced against each row from
483
469
the ``addresses`` table. So to put some sanity into this statement, we need a
484
 
WHERE clause. Which brings us to the second argument of :func:`.select`:
 
470
WHERE clause.  We do that using :meth:`.Select.where`:
485
471
 
486
472
.. sourcecode:: pycon+sql
487
473
 
488
 
    >>> s = select([users, addresses], users.c.id==addresses.c.user_id)
 
474
    >>> s = select([users, addresses]).where(users.c.id == addresses.c.user_id)
489
475
    {sql}>>> for row in conn.execute(s):
490
476
    ...     print row  # doctest: +NORMALIZE_WHITESPACE
491
 
    SELECT users.id, users.name, users.fullname, addresses.id, addresses.user_id, addresses.email_address
 
477
    SELECT users.id, users.name, users.fullname, addresses.id,
 
478
       addresses.user_id, addresses.email_address
492
479
    FROM users, addresses
493
480
    WHERE users.id = addresses.user_id
494
481
    ()
503
490
``addresses`` rows made sense. But let's look at that expression? It's using
504
491
just a Python equality operator between two different
505
492
:class:`~sqlalchemy.schema.Column` objects. It should be clear that something
506
 
is up. Saying ``1==1`` produces ``True``, and ``1==2`` produces ``False``, not
 
493
is up. Saying ``1 == 1`` produces ``True``, and ``1 == 2`` produces ``False``, not
507
494
a WHERE clause. So lets see exactly what that expression is doing:
508
495
 
509
496
.. sourcecode:: pycon+sql
510
497
 
511
 
    >>> users.c.id==addresses.c.user_id #doctest: +ELLIPSIS
512
 
    <sqlalchemy.sql.expression._BinaryExpression object at 0x...>
 
498
    >>> users.c.id == addresses.c.user_id #doctest: +ELLIPSIS
 
499
    <sqlalchemy.sql.expression.BinaryExpression object at 0x...>
513
500
 
514
501
Wow, surprise ! This is neither a ``True`` nor a ``False``. Well what is it ?
515
502
 
516
503
.. sourcecode:: pycon+sql
517
504
 
518
 
    >>> str(users.c.id==addresses.c.user_id)
 
505
    >>> str(users.c.id == addresses.c.user_id)
519
506
    'users.id = addresses.user_id'
520
507
 
521
508
As you can see, the ``==`` operator is producing an object that is very much
522
 
like the :class:`~sqlalchemy.sql.expression.Insert` and :func:`.select`
 
509
like the :class:`~.expression.Insert` and :func:`.select`
523
510
objects we've made so far, thanks to Python's ``__eq__()`` builtin; you call
524
511
``str()`` on it and it produces SQL. By now, one can see that everything we
525
512
are working with is ultimately the same type of object. SQLAlchemy terms the
526
 
base class of all of these expressions as ``sqlalchemy.sql.ClauseElement``.
 
513
base class of all of these expressions as :class:`~.expression.ColumnElement`.
527
514
 
528
515
Operators
529
516
==========
533
520
 
534
521
.. sourcecode:: pycon+sql
535
522
 
536
 
    >>> print users.c.id==addresses.c.user_id
 
523
    >>> print users.c.id == addresses.c.user_id
537
524
    users.id = addresses.user_id
538
525
 
539
526
If we use a literal value (a literal meaning, not a SQLAlchemy clause object),
541
528
 
542
529
.. sourcecode:: pycon+sql
543
530
 
544
 
    >>> print users.c.id==7
 
531
    >>> print users.c.id == 7
545
532
    users.id = :id_1
546
533
 
547
 
The ``7`` literal is embedded in
548
 
:class:`~sqlalchemy.sql.expression.ClauseElement`; we can use the same trick
 
534
The ``7`` literal is embedded the resulting
 
535
:class:`~.expression.ColumnElement`; we can use the same trick
549
536
we did with the :class:`~sqlalchemy.sql.expression.Insert` object to see it:
550
537
 
551
538
.. sourcecode:: pycon+sql
552
539
 
553
 
    >>> (users.c.id==7).compile().params
 
540
    >>> (users.c.id == 7).compile().params
554
541
    {u'id_1': 7}
555
542
 
556
543
Most Python operators, as it turns out, produce a SQL expression here, like
576
563
    >>> print users.c.id + addresses.c.id
577
564
    users.id + addresses.id
578
565
 
579
 
Interestingly, the type of the :class:`~sqlalchemy.schema.Column` is important
580
 
! If we use ``+`` with two string based columns (recall we put types like
 
566
Interestingly, the type of the :class:`~sqlalchemy.schema.Column` is important!
 
567
If we use ``+`` with two string based columns (recall we put types like
581
568
:class:`~sqlalchemy.types.Integer` and :class:`~sqlalchemy.types.String` on
582
569
our :class:`~sqlalchemy.schema.Column` objects at the beginning), we get
583
570
something different:
592
579
 
593
580
.. sourcecode:: pycon+sql
594
581
 
595
 
    >>> print (users.c.name + users.c.fullname).compile(bind=create_engine('mysql://'))
 
582
    >>> print (users.c.name + users.c.fullname).\
 
583
    ...      compile(bind=create_engine('mysql://'))
596
584
    concat(users.name, users.fullname)
597
585
 
598
586
The above illustrates the SQL that's generated for an
599
 
:class:`~sqlalchemy.engine.base.Engine` that's connected to a MySQL database;
 
587
:class:`~sqlalchemy.engine.Engine` that's connected to a MySQL database;
600
588
the ``||`` operator now compiles as MySQL's ``concat()`` function.
601
589
 
602
590
If you have come across an operator which really isn't available, you can
603
 
always use the ``op()`` method; this generates whatever operator you need:
 
591
always use the :meth:`.ColumnOperators.op` method; this generates whatever operator you need:
604
592
 
605
593
.. sourcecode:: pycon+sql
606
594
 
613
601
 
614
602
is a bitwise AND of the value in `somecolumn`.
615
603
 
 
604
Operator Customization
 
605
-----------------------
 
606
 
 
607
While :meth:`.ColumnOperators.op` is handy to get at a custom operator in a hurry,
 
608
the Core supports fundamental customization and extension of the operator system at
 
609
the type level.   The behavior of existing operators can be modified on a per-type
 
610
basis, and new operations can be defined which become available for all column
 
611
expressions that are part of that particular type.  See the section :ref:`types_operators`
 
612
for a description.
 
613
 
 
614
 
 
615
 
616
616
Conjunctions
617
617
=============
618
618
 
620
620
We'd like to show off some of our operators inside of :func:`.select`
621
621
constructs. But we need to lump them together a little more, so let's first
622
622
introduce some conjunctions. Conjunctions are those little words like AND and
623
 
OR that put things together. We'll also hit upon NOT. AND, OR and NOT can work
 
623
OR that put things together. We'll also hit upon NOT. :func:`.and_`, :func:`.or_`,
 
624
and :func:`.not_` can work
624
625
from the corresponding functions SQLAlchemy provides (notice we also throw in
625
 
a LIKE):
 
626
a :meth:`~.ColumnOperators.like`):
626
627
 
627
628
.. sourcecode:: pycon+sql
628
629
 
629
630
    >>> from sqlalchemy.sql import and_, or_, not_
630
 
    >>> print and_(users.c.name.like('j%'), users.c.id==addresses.c.user_id, #doctest: +NORMALIZE_WHITESPACE
631
 
    ...     or_(addresses.c.email_address=='wendy@aol.com', addresses.c.email_address=='jack@yahoo.com'),
632
 
    ...     not_(users.c.id>5))
 
631
    >>> print and_(
 
632
    ...         users.c.name.like('j%'),
 
633
    ...         users.c.id == addresses.c.user_id, #doctest: +NORMALIZE_WHITESPACE
 
634
    ...         or_(
 
635
    ...              addresses.c.email_address == 'wendy@aol.com',
 
636
    ...              addresses.c.email_address == 'jack@yahoo.com'
 
637
    ...         ),
 
638
    ...         not_(users.c.id > 5)
 
639
    ...       )
633
640
    users.name LIKE :name_1 AND users.id = addresses.user_id AND
634
 
    (addresses.email_address = :email_address_1 OR addresses.email_address = :email_address_2)
 
641
    (addresses.email_address = :email_address_1
 
642
       OR addresses.email_address = :email_address_2)
635
643
    AND users.id <= :id_1
636
644
 
637
645
And you can also use the re-jiggered bitwise AND, OR and NOT operators,
640
648
 
641
649
.. sourcecode:: pycon+sql
642
650
 
643
 
    >>> print users.c.name.like('j%') & (users.c.id==addresses.c.user_id) &  \
644
 
    ...     ((addresses.c.email_address=='wendy@aol.com') | (addresses.c.email_address=='jack@yahoo.com')) \
 
651
    >>> print users.c.name.like('j%') & (users.c.id == addresses.c.user_id) &  \
 
652
    ...     (
 
653
    ...       (addresses.c.email_address == 'wendy@aol.com') | \
 
654
    ...       (addresses.c.email_address == 'jack@yahoo.com')
 
655
    ...     ) \
645
656
    ...     & ~(users.c.id>5) # doctest: +NORMALIZE_WHITESPACE
646
657
    users.name LIKE :name_1 AND users.id = addresses.user_id AND
647
 
    (addresses.email_address = :email_address_1 OR addresses.email_address = :email_address_2)
 
658
    (addresses.email_address = :email_address_1
 
659
        OR addresses.email_address = :email_address_2)
648
660
    AND users.id <= :id_1
649
661
 
650
662
So with all of this vocabulary, let's select all users who have an email
651
663
address at AOL or MSN, whose name starts with a letter between "m" and "z",
652
664
and we'll also generate a column containing their full name combined with
653
665
their email address. We will add two new constructs to this statement,
654
 
``between()`` and ``label()``. ``between()`` produces a BETWEEN clause, and
655
 
``label()`` is used in a column expression to produce labels using the ``AS``
 
666
:meth:`~.ColumnOperators.between` and :meth:`~.ColumnElement.label`.
 
667
:meth:`~.ColumnOperators.between` produces a BETWEEN clause, and
 
668
:meth:`~.ColumnElement.label` is used in a column expression to produce labels using the ``AS``
656
669
keyword; it's recommended when selecting from expressions that otherwise would
657
670
not have a name:
658
671
 
659
672
.. sourcecode:: pycon+sql
660
673
 
661
 
    >>> s = select([(users.c.fullname + ", " + addresses.c.email_address).label('title')],
662
 
    ...        and_(
663
 
    ...            users.c.id==addresses.c.user_id,
664
 
    ...            users.c.name.between('m', 'z'),
665
 
    ...           or_(
666
 
    ...              addresses.c.email_address.like('%@aol.com'),
667
 
    ...              addresses.c.email_address.like('%@msn.com')
 
674
    >>> s = select([(users.c.fullname +
 
675
    ...               ", " + addresses.c.email_address).
 
676
    ...                label('title')]).\
 
677
    ...        where(
 
678
    ...           and_(
 
679
    ...               users.c.id == addresses.c.user_id,
 
680
    ...               users.c.name.between('m', 'z'),
 
681
    ...               or_(
 
682
    ...                  addresses.c.email_address.like('%@aol.com'),
 
683
    ...                  addresses.c.email_address.like('%@msn.com')
 
684
    ...               )
668
685
    ...           )
669
686
    ...        )
670
 
    ...    )
671
 
    >>> print conn.execute(s).fetchall() #doctest: +NORMALIZE_WHITESPACE
 
687
    >>> conn.execute(s).fetchall() #doctest: +NORMALIZE_WHITESPACE
672
688
    SELECT users.fullname || ? || addresses.email_address AS title
673
689
    FROM users, addresses
674
690
    WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND
681
697
clause, the where clause, and also some other elements which we haven't
682
698
covered yet, which include ORDER BY, GROUP BY, and HAVING.
683
699
 
 
700
A shortcut to using :func:`.and_` is to chain together multiple
 
701
:meth:`~.Select.where` clauses.   The above can also be written as:
 
702
 
 
703
.. sourcecode:: pycon+sql
 
704
 
 
705
    >>> s = select([(users.c.fullname +
 
706
    ...               ", " + addresses.c.email_address).
 
707
    ...                label('title')]).\
 
708
    ...        where(users.c.id == addresses.c.user_id).\
 
709
    ...        where(users.c.name.between('m', 'z')).\
 
710
    ...        where(
 
711
    ...               or_(
 
712
    ...                  addresses.c.email_address.like('%@aol.com'),
 
713
    ...                  addresses.c.email_address.like('%@msn.com')
 
714
    ...               )
 
715
    ...        )
 
716
    >>> conn.execute(s).fetchall() #doctest: +NORMALIZE_WHITESPACE
 
717
    SELECT users.fullname || ? || addresses.email_address AS title
 
718
    FROM users, addresses
 
719
    WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND
 
720
    (addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
 
721
    (', ', 'm', 'z', '%@aol.com', '%@msn.com')
 
722
    [(u'Wendy Williams, wendy@aol.com',)]
 
723
 
 
724
The way that we can build up a :func:`.select` construct through successive
 
725
method calls is called :term:`method chaining`.
 
726
 
684
727
.. _sqlexpression_text:
685
728
 
686
729
Using Text
689
732
Our last example really became a handful to type. Going from what one
690
733
understands to be a textual SQL expression into a Python construct which
691
734
groups components together in a programmatic style can be hard. That's why
692
 
SQLAlchemy lets you just use strings too. The ``text()`` construct represents
693
 
any textual statement. To use bind parameters with ``text()``, always use the
694
 
named colon format. Such as below, we create a ``text()`` and execute it,
695
 
feeding in the bind parameters to the ``execute()`` method:
 
735
SQLAlchemy lets you just use strings too. The :func:`~.expression.text` construct represents
 
736
any textual statement, in a backend-agnostic way.
 
737
To use bind parameters with :func:`~.expression.text`, always use the
 
738
named colon format. Such as below, we create a :func:`~.expression.text` and execute it,
 
739
feeding in the bind parameters to the :meth:`~.Connection.execute` method:
696
740
 
697
741
.. sourcecode:: pycon+sql
698
742
 
699
743
    >>> from sqlalchemy.sql import text
700
 
    >>> s = text("""SELECT users.fullname || ', ' || addresses.email_address AS title
701
 
    ...            FROM users, addresses
702
 
    ...            WHERE users.id = addresses.user_id AND users.name BETWEEN :x AND :y AND
703
 
    ...            (addresses.email_address LIKE :e1 OR addresses.email_address LIKE :e2)
704
 
    ...        """)
705
 
    {sql}>>> print conn.execute(s, x='m', y='z', e1='%@aol.com', e2='%@msn.com').fetchall() # doctest:+NORMALIZE_WHITESPACE
 
744
    >>> s = text(
 
745
    ...     "SELECT users.fullname || ', ' || addresses.email_address AS title "
 
746
    ...         "FROM users, addresses "
 
747
    ...         "WHERE users.id = addresses.user_id "
 
748
    ...         "AND users.name BETWEEN :x AND :y "
 
749
    ...         "AND (addresses.email_address LIKE :e1 "
 
750
    ...             "OR addresses.email_address LIKE :e2)")
 
751
    {sql}>>> conn.execute(s, x='m', y='z', e1='%@aol.com', e2='%@msn.com').fetchall() # doctest:+NORMALIZE_WHITESPACE
706
752
    SELECT users.fullname || ', ' || addresses.email_address AS title
707
753
    FROM users, addresses
708
754
    WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND
710
756
    ('m', 'z', '%@aol.com', '%@msn.com')
711
757
    {stop}[(u'Wendy Williams, wendy@aol.com',)]
712
758
 
713
 
To gain a "hybrid" approach, the `select()` construct accepts strings for most
 
759
To gain a "hybrid" approach, the :func:`.select` construct accepts strings for most
714
760
of its arguments. Below we combine the usage of strings with our constructed
715
761
:func:`.select` object, by using the :func:`.select` object to structure the
716
762
statement, and strings to provide all the content within the structure. For
717
763
this example, SQLAlchemy is not given any :class:`~sqlalchemy.schema.Column`
718
764
or :class:`~sqlalchemy.schema.Table` objects in any of its expressions, so it
719
 
cannot generate a FROM clause. So we also give it the ``from_obj`` keyword
720
 
argument, which is a list of ``ClauseElements`` (or strings) to be placed
721
 
within the FROM clause:
 
765
cannot generate a FROM clause. So we also use the :meth:`~.Select.select_from`
 
766
method, which accepts a :class:`.FromClause` or string expression
 
767
to be placed within the FROM clause:
722
768
 
723
769
.. sourcecode:: pycon+sql
724
770
 
725
 
    >>> s = select(["users.fullname || ', ' || addresses.email_address AS title"],
726
 
    ...        and_(
727
 
    ...            "users.id = addresses.user_id",
728
 
    ...             "users.name BETWEEN 'm' AND 'z'",
729
 
    ...             "(addresses.email_address LIKE :x OR addresses.email_address LIKE :y)"
730
 
    ...        ),
731
 
    ...         from_obj=['users', 'addresses']
732
 
    ...    )
733
 
    {sql}>>> print conn.execute(s, x='%@aol.com', y='%@msn.com').fetchall() #doctest: +NORMALIZE_WHITESPACE
 
771
    >>> s = select([
 
772
    ...            "users.fullname || ', ' || addresses.email_address AS title"
 
773
    ...          ]).\
 
774
    ...           where(
 
775
    ...              and_(
 
776
    ...                 "users.id = addresses.user_id",
 
777
    ...                 "users.name BETWEEN 'm' AND 'z'",
 
778
    ...                 "(addresses.email_address LIKE :x OR addresses.email_address LIKE :y)"
 
779
    ...             )
 
780
    ...           ).select_from('users, addresses')
 
781
    {sql}>>> conn.execute(s, x='%@aol.com', y='%@msn.com').fetchall() #doctest: +NORMALIZE_WHITESPACE
734
782
    SELECT users.fullname || ', ' || addresses.email_address AS title
735
783
    FROM users, addresses
736
 
    WHERE users.id = addresses.user_id AND users.name BETWEEN 'm' AND 'z' AND (addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
 
784
    WHERE users.id = addresses.user_id AND users.name BETWEEN 'm' AND 'z'
 
785
    AND (addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
737
786
    ('%@aol.com', '%@msn.com')
738
787
    {stop}[(u'Wendy Williams, wendy@aol.com',)]
739
788
 
744
793
datatypes in use; for example, if our bind parameters required UTF-8 encoding
745
794
before going in, or conversion from a Python ``datetime`` into a string (as is
746
795
required with SQLite), we would have to add extra information to our
747
 
``text()`` construct. Similar issues arise on the result set side, where
 
796
:func:`~.expression.text` construct. Similar issues arise on the result set side, where
748
797
SQLAlchemy also performs type-specific data conversion in some cases; still
749
 
more information can be added to ``text()`` to work around this. But what we
 
798
more information can be added to :func:`~.expression.text` to work around this. But what we
750
799
really lose from our statement is the ability to manipulate it, transform it,
751
800
and analyze it. These features are critical when using the ORM, which makes
752
801
heavy usage of relational transformations. To show off what we mean, we'll
777
826
 
778
827
    >>> a1 = addresses.alias()
779
828
    >>> a2 = addresses.alias()
780
 
    >>> s = select([users], and_(
781
 
    ...        users.c.id==a1.c.user_id,
782
 
    ...        users.c.id==a2.c.user_id,
783
 
    ...        a1.c.email_address=='jack@msn.com',
784
 
    ...        a2.c.email_address=='jack@yahoo.com'
785
 
    ...   ))
786
 
    {sql}>>> print conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
829
    >>> s = select([users]).\
 
830
    ...        where(and_(
 
831
    ...            users.c.id == a1.c.user_id,
 
832
    ...            users.c.id == a2.c.user_id,
 
833
    ...            a1.c.email_address == 'jack@msn.com',
 
834
    ...            a2.c.email_address == 'jack@yahoo.com'
 
835
    ...        ))
 
836
    {sql}>>> conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
787
837
    SELECT users.id, users.name, users.fullname
788
838
    FROM users, addresses AS addresses_1, addresses AS addresses_2
789
 
    WHERE users.id = addresses_1.user_id AND users.id = addresses_2.user_id AND addresses_1.email_address = ? AND addresses_2.email_address = ?
 
839
    WHERE users.id = addresses_1.user_id
 
840
        AND users.id = addresses_2.user_id
 
841
        AND addresses_1.email_address = ?
 
842
        AND addresses_2.email_address = ?
790
843
    ('jack@msn.com', 'jack@yahoo.com')
791
844
    {stop}[(1, u'jack', u'Jack Jones')]
792
845
 
814
867
.. sourcecode:: pycon+sql
815
868
 
816
869
    >>> a1 = s.correlate(None).alias()
817
 
    >>> s = select([users.c.name], users.c.id==a1.c.id)
818
 
    {sql}>>> print conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
870
    >>> s = select([users.c.name]).where(users.c.id == a1.c.id)
 
871
    {sql}>>> conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
819
872
    SELECT users.name
820
 
    FROM users, (SELECT users.id AS id, users.name AS name, users.fullname AS fullname
821
 
    FROM users, addresses AS addresses_1, addresses AS addresses_2
822
 
    WHERE users.id = addresses_1.user_id AND users.id = addresses_2.user_id AND addresses_1.email_address = ? AND addresses_2.email_address = ?) AS anon_1
 
873
    FROM users,
 
874
        (SELECT users.id AS id, users.name AS name, users.fullname AS fullname
 
875
            FROM users, addresses AS addresses_1, addresses AS addresses_2
 
876
            WHERE users.id = addresses_1.user_id AND users.id = addresses_2.user_id
 
877
            AND addresses_1.email_address = ?
 
878
            AND addresses_2.email_address = ?) AS anon_1
823
879
    WHERE users.id = anon_1.id
824
880
    ('jack@msn.com', 'jack@yahoo.com')
825
881
    {stop}[(u'jack',)]
832
888
cornerstone of the SELECT is the JOIN expression. We've already been doing
833
889
joins in our examples, by just placing two tables in either the columns clause
834
890
or the where clause of the :func:`.select` construct. But if we want to make a
835
 
real "JOIN" or "OUTERJOIN" construct, we use the ``join()`` and
836
 
``outerjoin()`` methods, most commonly accessed from the left table in the
 
891
real "JOIN" or "OUTERJOIN" construct, we use the :meth:`~.FromClause.join` and
 
892
:meth:`~.FromClause.outerjoin` methods, most commonly accessed from the left table in the
837
893
join:
838
894
 
839
895
.. sourcecode:: pycon+sql
854
910
 
855
911
.. sourcecode:: pycon+sql
856
912
 
857
 
    >>> print users.join(addresses, addresses.c.email_address.like(users.c.name + '%'))
858
 
    users JOIN addresses ON addresses.email_address LIKE users.name || :name_1
 
913
    >>> print users.join(addresses,
 
914
    ...                 addresses.c.email_address.like(users.c.name + '%')
 
915
    ...             )
 
916
    users JOIN addresses ON addresses.email_address LIKE (users.name || :name_1)
859
917
 
860
918
When we create a :func:`.select` construct, SQLAlchemy looks around at the
861
919
tables we've mentioned and then places them in the FROM clause of the
862
920
statement. When we use JOINs however, we know what FROM clause we want, so
863
 
here we make usage of the ``from_obj`` keyword argument:
 
921
here we make use of the :meth:`~.Select.select_from` method:
864
922
 
865
923
.. sourcecode:: pycon+sql
866
924
 
867
 
    >>> s = select([users.c.fullname], from_obj=[
868
 
    ...    users.join(addresses, addresses.c.email_address.like(users.c.name + '%'))
869
 
    ...    ])
870
 
    {sql}>>> print conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
925
    >>> s = select([users.c.fullname]).select_from(
 
926
    ...    users.join(addresses,
 
927
    ...             addresses.c.email_address.like(users.c.name + '%'))
 
928
    ...    )
 
929
    {sql}>>> conn.execute(s).fetchall()  # doctest: +NORMALIZE_WHITESPACE
871
930
    SELECT users.fullname
872
 
    FROM users JOIN addresses ON addresses.email_address LIKE users.name || ?
 
931
    FROM users JOIN addresses ON addresses.email_address LIKE (users.name || ?)
873
932
    ('%',)
874
933
    {stop}[(u'Jack Jones',), (u'Jack Jones',), (u'Wendy Williams',)]
875
934
 
876
 
The ``outerjoin()`` function just creates ``LEFT OUTER JOIN`` constructs. It's
877
 
used just like ``join()``:
 
935
The :meth:`~.FromClause.outerjoin` method creates ``LEFT OUTER JOIN`` constructs,
 
936
and is used in the same way as :meth:`~.FromClause.join`:
878
937
 
879
938
.. sourcecode:: pycon+sql
880
939
 
881
 
    >>> s = select([users.c.fullname], from_obj=[users.outerjoin(addresses)])
 
940
    >>> s = select([users.c.fullname]).select_from(users.outerjoin(addresses))
882
941
    >>> print s  # doctest: +NORMALIZE_WHITESPACE
883
942
    SELECT users.fullname
884
 
    FROM users LEFT OUTER JOIN addresses ON users.id = addresses.user_id
 
943
        FROM users
 
944
        LEFT OUTER JOIN addresses ON users.id = addresses.user_id
885
945
 
886
946
That's the output ``outerjoin()`` produces, unless, of course, you're stuck in
887
947
a gig using Oracle prior to version 9, and you've set up your engine (which
898
958
If you don't know what that SQL means, don't worry ! The secret tribe of
899
959
Oracle DBAs don't want their black magic being found out ;).
900
960
 
901
 
Intro to Generative Selects
902
 
================================================
903
 
 
904
 
We've now gained the ability to construct very sophisticated statements. We
905
 
can use all kinds of operators, table constructs, text, joins, and aliases.
906
 
The point of all of this, as mentioned earlier, is not that it's an "easier"
907
 
or "better" way to write SQL than just writing a SQL statement yourself; the
908
 
point is that it's better for writing *programmatically generated* SQL which
909
 
can be morphed and adapted as needed in automated scenarios.
910
 
 
911
 
To support this, the :func:`.select` construct we've been working with
912
 
supports piecemeal construction, in addition to the "all at once" method we've
913
 
been doing. Suppose you're writing a search function, which receives criterion
914
 
and then must construct a select from it. To accomplish this, upon each
915
 
criterion encountered, you apply "generative" criterion to an existing
916
 
:func:`.select` construct with new elements, one at a time. We start with a
917
 
basic :func:`.select` constructed with the shortcut method available on the
918
 
``users`` table:
919
 
 
920
 
.. sourcecode:: pycon+sql
921
 
 
922
 
    >>> query = users.select()
923
 
    >>> print query  # doctest: +NORMALIZE_WHITESPACE
924
 
    SELECT users.id, users.name, users.fullname
925
 
    FROM users
926
 
 
927
 
We encounter search criterion of "name='jack'". So we apply WHERE criterion
928
 
stating such:
929
 
 
930
 
.. sourcecode:: pycon+sql
931
 
 
932
 
    >>> query = query.where(users.c.name=='jack')
933
 
 
934
 
Next, we encounter that they'd like the results in descending order by full
935
 
name. We apply ORDER BY, using an extra modifier ``desc``:
936
 
 
937
 
.. sourcecode:: pycon+sql
938
 
 
939
 
    >>> query = query.order_by(users.c.fullname.desc())
940
 
 
941
 
We also come across that they'd like only users who have an address at MSN. A
942
 
quick way to tack this on is by using an EXISTS clause, which we correlate to
943
 
the ``users`` table in the enclosing SELECT:
944
 
 
945
 
.. sourcecode:: pycon+sql
946
 
 
947
 
    >>> from sqlalchemy.sql import exists
948
 
    >>> query = query.where(
949
 
    ...    exists([addresses.c.id],
950
 
    ...        and_(addresses.c.user_id==users.c.id, addresses.c.email_address.like('%@msn.com'))
951
 
    ...    ).correlate(users))
952
 
 
953
 
And finally, the application also wants to see the listing of email addresses
954
 
at once; so to save queries, we outerjoin the ``addresses`` table (using an
955
 
outer join so that users with no addresses come back as well; since we're
956
 
programmatic, we might not have kept track that we used an EXISTS clause
957
 
against the ``addresses`` table too...). Additionally, since the ``users`` and
958
 
``addresses`` table both have a column named ``id``, let's isolate their names
959
 
from each other in the COLUMNS clause by using labels:
960
 
 
961
 
.. sourcecode:: pycon+sql
962
 
 
963
 
    >>> query = query.column(addresses).select_from(users.outerjoin(addresses)).apply_labels()
964
 
 
965
 
Let's bake for .0001 seconds and see what rises:
966
 
 
967
 
.. sourcecode:: pycon+sql
968
 
 
969
 
    >>> conn.execute(query).fetchall()  # doctest: +NORMALIZE_WHITESPACE
970
 
    {opensql}SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, addresses.id AS addresses_id, addresses.user_id AS addresses_user_id, addresses.email_address AS addresses_email_address
971
 
    FROM users LEFT OUTER JOIN addresses ON users.id = addresses.user_id
972
 
    WHERE users.name = ? AND (EXISTS (SELECT addresses.id
973
 
    FROM addresses
974
 
    WHERE addresses.user_id = users.id AND addresses.email_address LIKE ?)) ORDER BY users.fullname DESC
975
 
    ('jack', '%@msn.com')
976
 
    {stop}[(1, u'jack', u'Jack Jones', 1, 1, u'jack@yahoo.com'), (1, u'jack', u'Jack Jones', 2, 1, u'jack@msn.com')]
977
 
 
978
 
The generative approach is about starting small, adding one thing at a time,
979
 
to arrive with a full statement.
980
 
 
981
 
Transforming a Statement
982
 
------------------------
983
 
 
984
 
We've seen how methods like :meth:`.Select.where` and :meth:`._SelectBase.order_by` are
985
 
part of the so-called *Generative* family of methods on the :func:`.select` construct,
986
 
where one :func:`.select` copies itself to return a new one with modifications.
987
 
SQL constructs also support another form of generative behavior which is
988
 
the *transformation*.   This is an advanced technique that most core applications
989
 
won't use directly; however, it is a system which the ORM relies on heavily,
990
 
and can be useful for any system that deals with generalized behavior of Core SQL
991
 
constructs.
992
 
 
993
 
Using a transformation we can take our ``users``/``addresses`` query and replace
994
 
all occurrences of ``addresses`` with an alias of itself.   That is, anywhere
995
 
that ``addresses`` is referred to in the original query, the new query will
996
 
refer to ``addresses_1``, which is selected as ``addresses AS addresses_1``.
997
 
The :meth:`.FromClause.replace_selectable` method can achieve this:
998
 
 
999
 
.. sourcecode:: pycon+sql
1000
 
 
1001
 
    >>> a1 = addresses.alias()
1002
 
    >>> query = query.replace_selectable(addresses, a1)
1003
 
    >>> print query  # doctest: +NORMALIZE_WHITESPACE
1004
 
    {opensql}SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, addresses_1.id AS addresses_1_id, addresses_1.user_id AS addresses_1_user_id, addresses_1.email_address AS addresses_1_email_address
1005
 
    FROM users LEFT OUTER JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id
1006
 
    WHERE users.name = :name_1 AND (EXISTS (SELECT addresses_1.id
1007
 
    FROM addresses AS addresses_1
1008
 
    WHERE addresses_1.user_id = users.id AND addresses_1.email_address LIKE :email_address_1)) ORDER BY users.fullname DESC
1009
 
 
1010
 
For a query such as the above, we can access the columns referred
1011
 
to by the ``a1`` alias in a result set using the :class:`.Column` objects
1012
 
present directly on ``a1``:
1013
 
 
1014
 
.. sourcecode:: pycon+sql
1015
 
 
1016
 
    {sql}>>> for row in conn.execute(query):
1017
 
    ...     print "Name:", row[users.c.name], "; Email Address", row[a1.c.email_address]  # doctest: +NORMALIZE_WHITESPACE
1018
 
    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, addresses_1.id AS addresses_1_id, addresses_1.user_id AS addresses_1_user_id, addresses_1.email_address AS addresses_1_email_address
1019
 
    FROM users LEFT OUTER JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id
1020
 
    WHERE users.name = ? AND (EXISTS (SELECT addresses_1.id
1021
 
    FROM addresses AS addresses_1
1022
 
    WHERE addresses_1.user_id = users.id AND addresses_1.email_address LIKE ?)) ORDER BY users.fullname DESC
1023
 
    ('jack', '%@msn.com')
1024
 
    {stop}Name: jack ; Email Address jack@yahoo.com
1025
 
    Name: jack ; Email Address jack@msn.com
1026
 
 
1027
961
Everything Else
1028
962
================
1029
963
 
1043
977
.. sourcecode:: pycon+sql
1044
978
 
1045
979
    >>> from sqlalchemy.sql import bindparam
1046
 
    >>> s = users.select(users.c.name==bindparam('username'))
 
980
    >>> s = users.select(users.c.name == bindparam('username'))
1047
981
    {sql}>>> conn.execute(s, username='wendy').fetchall() # doctest: +NORMALIZE_WHITESPACE
1048
982
    SELECT users.id, users.name, users.fullname
1049
983
    FROM users
1062
996
    {sql}>>> conn.execute(s, username='wendy').fetchall() # doctest: +NORMALIZE_WHITESPACE
1063
997
    SELECT users.id, users.name, users.fullname
1064
998
    FROM users
1065
 
    WHERE users.name LIKE ? || '%'
 
999
    WHERE users.name LIKE (? || '%')
1066
1000
    ('wendy',)
1067
1001
    {stop}[(2, u'wendy', u'Wendy Williams')]
1068
1002
 
1072
1006
 
1073
1007
.. sourcecode:: pycon+sql
1074
1008
 
1075
 
    >>> s = select([users, addresses],
1076
 
    ...    users.c.name.like(bindparam('name', type_=String) + text("'%'")) |
1077
 
    ...    addresses.c.email_address.like(bindparam('name', type_=String) + text("'@%'")),
1078
 
    ...    from_obj=[users.outerjoin(addresses)])
 
1009
    >>> s = select([users, addresses]).\
 
1010
    ...     where(
 
1011
    ...        or_(
 
1012
    ...          users.c.name.like(
 
1013
    ...                 bindparam('name', type_=String) + text("'%'")),
 
1014
    ...          addresses.c.email_address.like(
 
1015
    ...                 bindparam('name', type_=String) + text("'@%'"))
 
1016
    ...        )
 
1017
    ...     ).\
 
1018
    ...     select_from(users.outerjoin(addresses)).\
 
1019
    ...     order_by(addresses.c.id)
1079
1020
    {sql}>>> conn.execute(s, name='jack').fetchall() # doctest: +NORMALIZE_WHITESPACE
1080
 
    SELECT users.id, users.name, users.fullname, addresses.id, addresses.user_id, addresses.email_address
 
1021
    SELECT users.id, users.name, users.fullname, addresses.id,
 
1022
        addresses.user_id, addresses.email_address
1081
1023
    FROM users LEFT OUTER JOIN addresses ON users.id = addresses.user_id
1082
 
    WHERE users.name LIKE ? || '%' OR addresses.email_address LIKE ? || '@%'
 
1024
    WHERE users.name LIKE (? || '%') OR addresses.email_address LIKE (? || '@%')
 
1025
    ORDER BY addresses.id
1083
1026
    ('jack', 'jack')
1084
1027
    {stop}[(1, u'jack', u'Jack Jones', 1, 1, u'jack@yahoo.com'), (1, u'jack', u'Jack Jones', 2, 1, u'jack@msn.com')]
1085
1028
 
1086
1029
Functions
1087
1030
---------
1088
1031
 
1089
 
SQL functions are created using the :attr:`~.expression.func` keyword, which
 
1032
SQL functions are created using the :data:`~.expression.func` keyword, which
1090
1033
generates functions using attribute access:
1091
1034
 
1092
1035
.. sourcecode:: pycon+sql
1124
1067
 
1125
1068
.. sourcecode:: pycon+sql
1126
1069
 
1127
 
    >>> print conn.execute(
1128
 
    ...     select([func.max(addresses.c.email_address, type_=String).label('maxemail')])
1129
 
    ... ).scalar() # doctest: +NORMALIZE_WHITESPACE
 
1070
    >>> conn.execute(
 
1071
    ...     select([
 
1072
    ...            func.max(addresses.c.email_address, type_=String).
 
1073
    ...                label('maxemail')
 
1074
    ...           ])
 
1075
    ...     ).scalar() # doctest: +NORMALIZE_WHITESPACE
1130
1076
    {opensql}SELECT max(addresses.email_address) AS maxemail
1131
1077
    FROM addresses
1132
1078
    ()
1133
 
    {stop}www@www.org
 
1079
    {stop}u'www@www.org'
1134
1080
 
1135
1081
Databases such as PostgreSQL and Oracle which support functions that return
1136
1082
whole result sets can be assembled into selectable units, which can be used in
1142
1088
.. sourcecode:: pycon+sql
1143
1089
 
1144
1090
    >>> from sqlalchemy.sql import column
1145
 
    >>> calculate = select([column('q'), column('z'), column('r')],
1146
 
    ...     from_obj=[func.calculate(bindparam('x'), bindparam('y'))])
1147
 
 
1148
 
    >>> print select([users], users.c.id > calculate.c.z) # doctest: +NORMALIZE_WHITESPACE
 
1091
    >>> calculate = select([column('q'), column('z'), column('r')]).\
 
1092
    ...        select_from(
 
1093
    ...             func.calculate(
 
1094
    ...                    bindparam('x'),
 
1095
    ...                    bindparam('y')
 
1096
    ...                )
 
1097
    ...             )
 
1098
    >>> calc = calculate.alias()
 
1099
    >>> print select([users]).where(users.c.id > calc.c.z) # doctest: +NORMALIZE_WHITESPACE
1149
1100
    SELECT users.id, users.name, users.fullname
1150
1101
    FROM users, (SELECT q, z, r
1151
 
    FROM calculate(:x, :y))
1152
 
    WHERE users.id > z
 
1102
    FROM calculate(:x, :y)) AS anon_1
 
1103
    WHERE users.id > anon_1.z
1153
1104
 
1154
1105
If we wanted to use our ``calculate`` statement twice with different bind
1155
1106
parameters, the :func:`~sqlalchemy.sql.expression.ClauseElement.unique_params`
1159
1110
 
1160
1111
.. sourcecode:: pycon+sql
1161
1112
 
1162
 
    >>> s = select([users], users.c.id.between(
1163
 
    ...    calculate.alias('c1').unique_params(x=17, y=45).c.z,
1164
 
    ...    calculate.alias('c2').unique_params(x=5, y=12).c.z))
1165
 
 
 
1113
    >>> calc1 = calculate.alias('c1').unique_params(x=17, y=45)
 
1114
    >>> calc2 = calculate.alias('c2').unique_params(x=5, y=12)
 
1115
    >>> s = select([users]).\
 
1116
    ...         where(users.c.id.between(calc1.c.z, calc2.c.z))
1166
1117
    >>> print s # doctest: +NORMALIZE_WHITESPACE
1167
1118
    SELECT users.id, users.name, users.fullname
1168
 
    FROM users, (SELECT q, z, r
1169
 
    FROM calculate(:x_1, :y_1)) AS c1, (SELECT q, z, r
1170
 
    FROM calculate(:x_2, :y_2)) AS c2
 
1119
    FROM users,
 
1120
        (SELECT q, z, r FROM calculate(:x_1, :y_1)) AS c1,
 
1121
        (SELECT q, z, r FROM calculate(:x_2, :y_2)) AS c2
1171
1122
    WHERE users.id BETWEEN c1.z AND c2.z
1172
1123
 
1173
1124
    >>> s.compile().params
1174
1125
    {u'x_2': 5, u'y_2': 12, u'y_1': 45, u'x_1': 17}
1175
1126
 
1176
 
See also :attr:`sqlalchemy.sql.expression.func`.
1177
1127
 
1178
1128
Window Functions
1179
1129
-----------------
1180
1130
 
1181
1131
Any :class:`.FunctionElement`, including functions generated by
1182
 
:attr:`~.expression.func`, can be turned into a "window function", that is an
 
1132
:data:`~.expression.func`, can be turned into a "window function", that is an
1183
1133
OVER clause, using the :meth:`~.FunctionElement.over` method:
1184
1134
 
1185
1135
.. sourcecode:: pycon+sql
1186
1136
 
1187
 
    >>> s = select([users.c.id, func.row_number().over(order_by=users.c.name)])
 
1137
    >>> s = select([
 
1138
    ...         users.c.id,
 
1139
    ...         func.row_number().over(order_by=users.c.name)
 
1140
    ...     ])
1188
1141
    >>> print s # doctest: +NORMALIZE_WHITESPACE
1189
1142
    SELECT users.id, row_number() OVER (ORDER BY users.name) AS anon_1
1190
1143
    FROM users
1193
1146
-------------------------------
1194
1147
 
1195
1148
Unions come in two flavors, UNION and UNION ALL, which are available via
1196
 
module level functions:
 
1149
module level functions :func:`~.expression.union` and
 
1150
:func:`~.expression.union_all`:
1197
1151
 
1198
1152
.. sourcecode:: pycon+sql
1199
1153
 
1200
1154
    >>> from sqlalchemy.sql import union
1201
1155
    >>> u = union(
1202
 
    ...     addresses.select(addresses.c.email_address=='foo@bar.com'),
1203
 
    ...    addresses.select(addresses.c.email_address.like('%@yahoo.com')),
 
1156
    ...     addresses.select().
 
1157
    ...             where(addresses.c.email_address == 'foo@bar.com'),
 
1158
    ...    addresses.select().
 
1159
    ...             where(addresses.c.email_address.like('%@yahoo.com')),
1204
1160
    ... ).order_by(addresses.c.email_address)
1205
1161
 
1206
 
    {sql}>>> print conn.execute(u).fetchall() # doctest: +NORMALIZE_WHITESPACE
 
1162
    {sql}>>> conn.execute(u).fetchall() # doctest: +NORMALIZE_WHITESPACE
1207
1163
    SELECT addresses.id, addresses.user_id, addresses.email_address
1208
1164
    FROM addresses
1209
 
    WHERE addresses.email_address = ? UNION SELECT addresses.id, addresses.user_id, addresses.email_address
 
1165
    WHERE addresses.email_address = ?
 
1166
    UNION
 
1167
    SELECT addresses.id, addresses.user_id, addresses.email_address
1210
1168
    FROM addresses
1211
1169
    WHERE addresses.email_address LIKE ? ORDER BY addresses.email_address
1212
1170
    ('foo@bar.com', '%@yahoo.com')
1213
1171
    {stop}[(1, 1, u'jack@yahoo.com')]
1214
1172
 
1215
 
Also available, though not supported on all databases, are ``intersect()``,
1216
 
``intersect_all()``, ``except_()``, and ``except_all()``:
 
1173
Also available, though not supported on all databases, are
 
1174
:func:`~.expression.intersect`,
 
1175
:func:`~.expression.intersect_all`,
 
1176
:func:`~.expression.except_`, and :func:`~.expression.except_all`:
1217
1177
 
1218
1178
.. sourcecode:: pycon+sql
1219
1179
 
1220
1180
    >>> from sqlalchemy.sql import except_
1221
1181
    >>> u = except_(
1222
 
    ...    addresses.select(addresses.c.email_address.like('%@%.com')),
1223
 
    ...    addresses.select(addresses.c.email_address.like('%@msn.com'))
 
1182
    ...    addresses.select().
 
1183
    ...             where(addresses.c.email_address.like('%@%.com')),
 
1184
    ...    addresses.select().
 
1185
    ...             where(addresses.c.email_address.like('%@msn.com'))
1224
1186
    ... )
1225
1187
 
1226
 
    {sql}>>> print conn.execute(u).fetchall() # doctest: +NORMALIZE_WHITESPACE
 
1188
    {sql}>>> conn.execute(u).fetchall() # doctest: +NORMALIZE_WHITESPACE
1227
1189
    SELECT addresses.id, addresses.user_id, addresses.email_address
1228
1190
    FROM addresses
1229
 
    WHERE addresses.email_address LIKE ? EXCEPT SELECT addresses.id, addresses.user_id, addresses.email_address
 
1191
    WHERE addresses.email_address LIKE ?
 
1192
    EXCEPT
 
1193
    SELECT addresses.id, addresses.user_id, addresses.email_address
1230
1194
    FROM addresses
1231
1195
    WHERE addresses.email_address LIKE ?
1232
1196
    ('%@%.com', '%@msn.com')
1244
1208
 
1245
1209
    >>> u = except_(
1246
1210
    ...    union(
1247
 
    ...         addresses.select(addresses.c.email_address.like('%@yahoo.com')),
1248
 
    ...         addresses.select(addresses.c.email_address.like('%@msn.com'))
 
1211
    ...         addresses.select().
 
1212
    ...             where(addresses.c.email_address.like('%@yahoo.com')),
 
1213
    ...         addresses.select().
 
1214
    ...             where(addresses.c.email_address.like('%@msn.com'))
1249
1215
    ...     ).alias().select(),   # apply subquery here
1250
1216
    ...    addresses.select(addresses.c.email_address.like('%@msn.com'))
1251
1217
    ... )
1252
 
    {sql}>>> print conn.execute(u).fetchall()   # doctest: +NORMALIZE_WHITESPACE
 
1218
    {sql}>>> conn.execute(u).fetchall()   # doctest: +NORMALIZE_WHITESPACE
1253
1219
    SELECT anon_1.id, anon_1.user_id, anon_1.email_address
1254
1220
    FROM (SELECT addresses.id AS id, addresses.user_id AS user_id,
1255
 
    addresses.email_address AS email_address FROM addresses
1256
 
    WHERE addresses.email_address LIKE ? UNION SELECT addresses.id AS id,
1257
 
    addresses.user_id AS user_id, addresses.email_address AS email_address
1258
 
    FROM addresses WHERE addresses.email_address LIKE ?) AS anon_1 EXCEPT
 
1221
        addresses.email_address AS email_address
 
1222
        FROM addresses
 
1223
        WHERE addresses.email_address LIKE ?
 
1224
        UNION
 
1225
        SELECT addresses.id AS id,
 
1226
            addresses.user_id AS user_id,
 
1227
            addresses.email_address AS email_address
 
1228
        FROM addresses
 
1229
        WHERE addresses.email_address LIKE ?) AS anon_1
 
1230
    EXCEPT
1259
1231
    SELECT addresses.id, addresses.user_id, addresses.email_address
1260
1232
    FROM addresses
1261
1233
    WHERE addresses.email_address LIKE ?
1262
1234
    ('%@yahoo.com', '%@msn.com', '%@msn.com')
1263
1235
    {stop}[(1, 1, u'jack@yahoo.com')]
1264
1236
 
 
1237
.. _scalar_selects:
1265
1238
 
1266
1239
Scalar Selects
1267
1240
--------------
1268
1241
 
1269
 
To embed a SELECT in a column expression, use
1270
 
:func:`~sqlalchemy.sql.expression._SelectBaseMixin.as_scalar`:
1271
 
 
1272
 
.. sourcecode:: pycon+sql
1273
 
 
1274
 
    {sql}>>> print conn.execute(select([   # doctest: +NORMALIZE_WHITESPACE
1275
 
    ...       users.c.name,
1276
 
    ...       select([func.count(addresses.c.id)], users.c.id==addresses.c.user_id).as_scalar()
1277
 
    ...    ])).fetchall()
1278
 
    SELECT users.name, (SELECT count(addresses.id) AS count_1
 
1242
A scalar select is a SELECT that returns exactly one row and one
 
1243
column.  It can then be used as a column expression.  A scalar select
 
1244
is often a :term:`correlated subquery`, which relies upon the enclosing
 
1245
SELECT statement in order to acquire at least one of its FROM clauses.
 
1246
 
 
1247
The :func:`.select` construct can be modified to act as a
 
1248
column expression by calling either the :meth:`~.SelectBase.as_scalar`
 
1249
or :meth:`~.SelectBase.label` method:
 
1250
 
 
1251
.. sourcecode:: pycon+sql
 
1252
 
 
1253
    >>> stmt = select([func.count(addresses.c.id)]).\
 
1254
    ...             where(users.c.id == addresses.c.user_id).\
 
1255
    ...             as_scalar()
 
1256
 
 
1257
The above construct is now a :class:`~.expression.ScalarSelect` object,
 
1258
and is no longer part of the :class:`~.expression.FromClause` hierarchy;
 
1259
it instead is within the :class:`~.expression.ColumnElement` family of
 
1260
expression constructs.  We can place this construct the same as any
 
1261
other column within another :func:`.select`:
 
1262
 
 
1263
.. sourcecode:: pycon+sql
 
1264
 
 
1265
    >>> conn.execute(select([users.c.name, stmt])).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1266
    {opensql}SELECT users.name, (SELECT count(addresses.id) AS count_1
1279
1267
    FROM addresses
1280
1268
    WHERE users.id = addresses.user_id) AS anon_1
1281
1269
    FROM users
1282
1270
    ()
1283
 
    {stop}[(u'jack', 2), (u'wendy', 2), (u'fred', 0), (u'mary', 0)]
 
1271
    {stop}[(u'jack', 2), (u'wendy', 2)]
1284
1272
 
1285
 
Alternatively, applying a ``label()`` to a select evaluates it as a scalar as
1286
 
well:
 
1273
To apply a non-anonymous column name to our scalar select, we create
 
1274
it using :meth:`.SelectBase.label` instead:
1287
1275
 
1288
1276
.. sourcecode:: pycon+sql
1289
1277
 
1290
 
    {sql}>>> print conn.execute(select([    # doctest: +NORMALIZE_WHITESPACE
1291
 
    ...       users.c.name,
1292
 
    ...       select([func.count(addresses.c.id)], users.c.id==addresses.c.user_id).label('address_count')
1293
 
    ...    ])).fetchall()
1294
 
    SELECT users.name, (SELECT count(addresses.id) AS count_1
 
1278
    >>> stmt = select([func.count(addresses.c.id)]).\
 
1279
    ...             where(users.c.id == addresses.c.user_id).\
 
1280
    ...             label("address_count")
 
1281
    >>> conn.execute(select([users.c.name, stmt])).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1282
    {opensql}SELECT users.name, (SELECT count(addresses.id) AS count_1
1295
1283
    FROM addresses
1296
1284
    WHERE users.id = addresses.user_id) AS address_count
1297
1285
    FROM users
1298
1286
    ()
1299
 
    {stop}[(u'jack', 2), (u'wendy', 2), (u'fred', 0), (u'mary', 0)]
 
1287
    {stop}[(u'jack', 2), (u'wendy', 2)]
 
1288
 
 
1289
.. _correlated_subqueries:
1300
1290
 
1301
1291
Correlated Subqueries
1302
1292
---------------------
1303
1293
 
1304
 
Notice in the examples on "scalar selects", the FROM clause of each embedded
 
1294
Notice in the examples on :ref:`scalar_selects`, the FROM clause of each embedded
1305
1295
select did not contain the ``users`` table in its FROM clause. This is because
1306
 
SQLAlchemy automatically attempts to correlate embedded FROM objects to that
1307
 
of an enclosing query. To disable this, or to specify explicit FROM clauses to
1308
 
be correlated, use ``correlate()``::
1309
 
 
1310
 
    >>> s = select([users.c.name], users.c.id==select([users.c.id]).correlate(None))
1311
 
    >>> print s # doctest: +NORMALIZE_WHITESPACE
1312
 
    SELECT users.name
1313
 
    FROM users
1314
 
    WHERE users.id = (SELECT users.id
1315
 
    FROM users)
1316
 
 
1317
 
    >>> s = select([users.c.name, addresses.c.email_address], users.c.id==
1318
 
    ...        select([users.c.id], users.c.id==addresses.c.user_id).correlate(addresses)
1319
 
    ...    )
1320
 
    >>> print s # doctest: +NORMALIZE_WHITESPACE
1321
 
    SELECT users.name, addresses.email_address
1322
 
    FROM users, addresses
1323
 
    WHERE users.id = (SELECT users.id
1324
 
    FROM users
1325
 
    WHERE users.id = addresses.user_id)
 
1296
SQLAlchemy automatically :term:`correlates` embedded FROM objects to that
 
1297
of an enclosing query, if present, and if the inner SELECT statement would
 
1298
still have at least one FROM clause of its own.  For example:
 
1299
 
 
1300
.. sourcecode:: pycon+sql
 
1301
 
 
1302
    >>> stmt = select([addresses.c.user_id]).\
 
1303
    ...             where(addresses.c.user_id == users.c.id).\
 
1304
    ...             where(addresses.c.email_address == 'jack@yahoo.com')
 
1305
    >>> enclosing_stmt = select([users.c.name]).where(users.c.id == stmt)
 
1306
    >>> conn.execute(enclosing_stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1307
    {opensql}SELECT users.name
 
1308
    FROM users
 
1309
    WHERE users.id = (SELECT addresses.user_id
 
1310
        FROM addresses
 
1311
        WHERE addresses.user_id = users.id
 
1312
        AND addresses.email_address = ?)
 
1313
    ('jack@yahoo.com',)
 
1314
    {stop}[(u'jack',)]
 
1315
 
 
1316
Auto-correlation will usually do what's expected, however it can also be controlled.
 
1317
For example, if we wanted a statement to correlate only to the ``addresses`` table
 
1318
but not the ``users`` table, even if both were present in the enclosing SELECT,
 
1319
we use the :meth:`~.Select.correlate` method to specify those FROM clauses that
 
1320
may be correlated:
 
1321
 
 
1322
.. sourcecode:: pycon+sql
 
1323
 
 
1324
    >>> stmt = select([users.c.id]).\
 
1325
    ...             where(users.c.id == addresses.c.user_id).\
 
1326
    ...             where(users.c.name == 'jack').\
 
1327
    ...             correlate(addresses)
 
1328
    >>> enclosing_stmt = select(
 
1329
    ...         [users.c.name, addresses.c.email_address]).\
 
1330
    ...     select_from(users.join(addresses)).\
 
1331
    ...     where(users.c.id == stmt)
 
1332
    >>> conn.execute(enclosing_stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1333
    {opensql}SELECT users.name, addresses.email_address
 
1334
     FROM users JOIN addresses ON users.id = addresses.user_id
 
1335
     WHERE users.id = (SELECT users.id
 
1336
     FROM users
 
1337
     WHERE users.id = addresses.user_id AND users.name = ?)
 
1338
     ('jack',)
 
1339
     {stop}[(u'jack', u'jack@yahoo.com'), (u'jack', u'jack@msn.com')]
 
1340
 
 
1341
To entirely disable a statement from correlating, we can pass ``None``
 
1342
as the argument:
 
1343
 
 
1344
.. sourcecode:: pycon+sql
 
1345
 
 
1346
    >>> stmt = select([users.c.id]).\
 
1347
    ...             where(users.c.name == 'wendy').\
 
1348
    ...             correlate(None)
 
1349
    >>> enclosing_stmt = select([users.c.name]).\
 
1350
    ...     where(users.c.id == stmt)
 
1351
    >>> conn.execute(enclosing_stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1352
    {opensql}SELECT users.name
 
1353
     FROM users
 
1354
     WHERE users.id = (SELECT users.id
 
1355
      FROM users
 
1356
      WHERE users.name = ?)
 
1357
    ('wendy',)
 
1358
    {stop}[(u'wendy',)]
 
1359
 
 
1360
We can also control correlation via exclusion, using the :meth:`.Select.correlate_except`
 
1361
method.   Such as, we can write our SELECT for the ``users`` table
 
1362
by telling it to correlate all FROM clauses except for ``users``:
 
1363
 
 
1364
.. sourcecode:: pycon+sql
 
1365
 
 
1366
    >>> stmt = select([users.c.id]).\
 
1367
    ...             where(users.c.id == addresses.c.user_id).\
 
1368
    ...             where(users.c.name == 'jack').\
 
1369
    ...             correlate_except(users)
 
1370
    >>> enclosing_stmt = select(
 
1371
    ...         [users.c.name, addresses.c.email_address]).\
 
1372
    ...     select_from(users.join(addresses)).\
 
1373
    ...     where(users.c.id == stmt)
 
1374
    >>> conn.execute(enclosing_stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1375
    {opensql}SELECT users.name, addresses.email_address
 
1376
     FROM users JOIN addresses ON users.id = addresses.user_id
 
1377
     WHERE users.id = (SELECT users.id
 
1378
     FROM users
 
1379
     WHERE users.id = addresses.user_id AND users.name = ?)
 
1380
     ('jack',)
 
1381
     {stop}[(u'jack', u'jack@yahoo.com'), (u'jack', u'jack@msn.com')]
1326
1382
 
1327
1383
Ordering, Grouping, Limiting, Offset...ing...
1328
1384
---------------------------------------------
1329
1385
 
1330
 
 
1331
 
The :func:`.select` function can take keyword arguments ``order_by``,
1332
 
``group_by`` (as well as ``having``), ``limit``, and ``offset``. There's also
1333
 
``distinct=True``. These are all also available as generative functions.
1334
 
``order_by()`` expressions can use the modifiers ``asc()`` or ``desc()`` to
1335
 
indicate ascending or descending.
1336
 
 
1337
 
.. sourcecode:: pycon+sql
1338
 
 
1339
 
    >>> s = select([addresses.c.user_id, func.count(addresses.c.id)]).\
1340
 
    ...     group_by(addresses.c.user_id).having(func.count(addresses.c.id)>1)
1341
 
    {sql}>>> print conn.execute(s).fetchall() # doctest: +NORMALIZE_WHITESPACE
1342
 
    SELECT addresses.user_id, count(addresses.id) AS count_1
1343
 
    FROM addresses GROUP BY addresses.user_id
1344
 
    HAVING count(addresses.id) > ?
1345
 
    (1,)
1346
 
    {stop}[(1, 2), (2, 2)]
1347
 
 
1348
 
    >>> s = select([addresses.c.email_address, addresses.c.id]).distinct().\
1349
 
    ...     order_by(addresses.c.email_address.desc(), addresses.c.id)
1350
 
    {sql}>>> conn.execute(s).fetchall() # doctest: +NORMALIZE_WHITESPACE
1351
 
    SELECT DISTINCT addresses.email_address, addresses.id
1352
 
    FROM addresses ORDER BY addresses.email_address DESC, addresses.id
1353
 
    ()
1354
 
    {stop}[(u'www@www.org', 3), (u'wendy@aol.com', 4), (u'jack@yahoo.com', 1), (u'jack@msn.com', 2)]
1355
 
 
1356
 
    >>> s = select([addresses]).offset(1).limit(1)
1357
 
    {sql}>>> print conn.execute(s).fetchall() # doctest: +NORMALIZE_WHITESPACE
1358
 
    SELECT addresses.id, addresses.user_id, addresses.email_address
1359
 
    FROM addresses
1360
 
    LIMIT 1 OFFSET 1
1361
 
    ()
1362
 
    {stop}[(2, 1, u'jack@msn.com')]
 
1386
Ordering is done by passing column expressions to the
 
1387
:meth:`~.SelectBase.order_by` method:
 
1388
 
 
1389
.. sourcecode:: pycon+sql
 
1390
 
 
1391
    >>> stmt = select([users.c.name]).order_by(users.c.name)
 
1392
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1393
    {opensql}SELECT users.name
 
1394
    FROM users ORDER BY users.name
 
1395
    ()
 
1396
    {stop}[(u'jack',), (u'wendy',)]
 
1397
 
 
1398
Ascending or descending can be controlled using the :meth:`~.ColumnElement.asc`
 
1399
and :meth:`~.ColumnElement.desc` modifiers:
 
1400
 
 
1401
.. sourcecode:: pycon+sql
 
1402
 
 
1403
    >>> stmt = select([users.c.name]).order_by(users.c.name.desc())
 
1404
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1405
    {opensql}SELECT users.name
 
1406
    FROM users ORDER BY users.name DESC
 
1407
    ()
 
1408
    {stop}[(u'wendy',), (u'jack',)]
 
1409
 
 
1410
Grouping refers to the GROUP BY clause, and is usually used in conjunction
 
1411
with aggregate functions to establish groups of rows to be aggregated.
 
1412
This is provided via the :meth:`~.SelectBase.group_by` method:
 
1413
 
 
1414
.. sourcecode:: pycon+sql
 
1415
 
 
1416
    >>> stmt = select([users.c.name, func.count(addresses.c.id)]).\
 
1417
    ...             select_from(users.join(addresses)).\
 
1418
    ...             group_by(users.c.name)
 
1419
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1420
    {opensql}SELECT users.name, count(addresses.id) AS count_1
 
1421
    FROM users JOIN addresses
 
1422
        ON users.id = addresses.user_id
 
1423
    GROUP BY users.name
 
1424
    ()
 
1425
    {stop}[(u'jack', 2), (u'wendy', 2)]
 
1426
 
 
1427
HAVING can be used to filter results on an aggregate value, after GROUP BY has
 
1428
been applied.  It's available here via the :meth:`~.Select.having`
 
1429
method:
 
1430
 
 
1431
.. sourcecode:: pycon+sql
 
1432
 
 
1433
    >>> stmt = select([users.c.name, func.count(addresses.c.id)]).\
 
1434
    ...             select_from(users.join(addresses)).\
 
1435
    ...             group_by(users.c.name).\
 
1436
    ...             having(func.length(users.c.name) > 4)
 
1437
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1438
    {opensql}SELECT users.name, count(addresses.id) AS count_1
 
1439
    FROM users JOIN addresses
 
1440
        ON users.id = addresses.user_id
 
1441
    GROUP BY users.name
 
1442
    HAVING length(users.name) > ?
 
1443
    (4,)
 
1444
    {stop}[(u'wendy', 2)]
 
1445
 
 
1446
A common system of dealing with duplicates in composed SELECT statments
 
1447
is the DISTINCT modifier.  A simple DISTINCT clause can be added using the
 
1448
:meth:`.Select.distinct` method:
 
1449
 
 
1450
.. sourcecode:: pycon+sql
 
1451
 
 
1452
    >>> stmt = select([users.c.name]).\
 
1453
    ...             where(addresses.c.email_address.
 
1454
    ...                    contains(users.c.name)).\
 
1455
    ...             distinct()
 
1456
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1457
    {opensql}SELECT DISTINCT users.name
 
1458
    FROM users, addresses
 
1459
    WHERE addresses.email_address LIKE '%%' || users.name || '%%'
 
1460
    ()
 
1461
    {stop}[(u'jack',), (u'wendy',)]
 
1462
 
 
1463
Most database backends support a system of limiting how many rows
 
1464
are returned, and the majority also feature a means of starting to return
 
1465
rows after a given "offset".   While common backends like Postgresql,
 
1466
MySQL and SQLite support LIMIT and OFFSET keywords, other backends
 
1467
need to refer to more esoteric features such as "window functions"
 
1468
and row ids to achieve the same effect.  The :meth:`~.Select.limit`
 
1469
and :meth:`~.Select.offset` methods provide an easy abstraction
 
1470
into the current backend's methodology:
 
1471
 
 
1472
.. sourcecode:: pycon+sql
 
1473
 
 
1474
    >>> stmt = select([users.c.name, addresses.c.email_address]).\
 
1475
    ...             select_from(users.join(addresses)).\
 
1476
    ...             limit(1).offset(1)
 
1477
    >>> conn.execute(stmt).fetchall()  # doctest: +NORMALIZE_WHITESPACE
 
1478
    {opensql}SELECT users.name, addresses.email_address
 
1479
    FROM users JOIN addresses ON users.id = addresses.user_id
 
1480
     LIMIT ? OFFSET ?
 
1481
    (1, 1)
 
1482
    {stop}[(u'jack', u'jack@msn.com')]
 
1483
 
1363
1484
 
1364
1485
.. _inserts_and_updates:
1365
1486
 
1366
 
Inserts and Updates
1367
 
===================
1368
 
 
1369
 
Finally, we're back to INSERT for some more detail. The
1370
 
:func:`~sqlalchemy.sql.expression.insert` construct provides a :meth:`~.ValuesBase.values`
1371
 
method which can be used to send any value or clause expression to the VALUES
1372
 
portion of the INSERT::
1373
 
 
1374
 
    # insert from a function
1375
 
    users.insert().values(id=12, name=func.upper('jack'))
1376
 
 
1377
 
    # insert from a concatenation expression
1378
 
    addresses.insert().values(email_address = name + '@' + host)
1379
 
 
1380
 
``values()`` can be mixed with per-execution values::
1381
 
 
1382
 
    conn.execute(
1383
 
        users.insert().values(name=func.upper('jack')),
1384
 
        fullname='Jack Jones'
1385
 
    )
1386
 
 
1387
 
:func:`~sqlalchemy.sql.expression.bindparam` constructs can be passed, however
1388
 
the names of the table's columns are reserved for the "automatic" generation
1389
 
of bind names::
1390
 
 
1391
 
    users.insert().values(id=bindparam('_id'), name=bindparam('_name'))
1392
 
 
1393
 
    # insert many rows at once:
1394
 
    conn.execute(
1395
 
        users.insert().values(id=bindparam('_id'), name=bindparam('_name')),
1396
 
        [
1397
 
            {'_id':1, '_name':'name1'},
1398
 
            {'_id':2, '_name':'name2'},
1399
 
            {'_id':3, '_name':'name3'},
1400
 
        ]
1401
 
    )
1402
 
 
1403
 
An UPDATE statement is emitted using the :func:`.update` construct.  These
1404
 
work much like an INSERT, except there is an additional WHERE clause
 
1487
Inserts, Updates and Deletes
 
1488
============================
 
1489
 
 
1490
We've seen :meth:`~.TableClause.insert` demonstrated
 
1491
earlier in this tutorial.   Where :meth:`~.TableClause.insert`
 
1492
prodces INSERT, the :meth:`~.TableClause.update`
 
1493
method produces UPDATE.  Both of these constructs feature
 
1494
a method called :meth:`~.ValuesBase.values` which specifies
 
1495
the VALUES or SET clause of the statement.
 
1496
 
 
1497
The :meth:`~.ValuesBase.values` method accommodates any column expression
 
1498
as a value:
 
1499
 
 
1500
.. sourcecode:: pycon+sql
 
1501
 
 
1502
    >>> stmt = users.update().\
 
1503
    ...             values(fullname="Fullname: " + users.c.name)
 
1504
    >>> conn.execute(stmt) #doctest: +ELLIPSIS
 
1505
    {opensql}UPDATE users SET fullname=(? || users.name)
 
1506
    ('Fullname: ',)
 
1507
    COMMIT
 
1508
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
 
1509
 
 
1510
When using :meth:`~.TableClause.insert` or :meth:`~.TableClause.update`
 
1511
in an "execute many" context, we may also want to specify named
 
1512
bound parameters which we can refer to in the argument list.
 
1513
The two constructs will automatically generate bound placeholders
 
1514
for any column names passed in the dictionaries sent to
 
1515
:meth:`~.Connection.execute` at execution time.  However, if we
 
1516
wish to use explicitly targeted named parameters with composed expressions,
 
1517
we need to use the :func:`~.expression.bindparam` construct.
 
1518
When using :func:`~.expression.bindparam` with
 
1519
:meth:`~.TableClause.insert` or :meth:`~.TableClause.update`,
 
1520
the names of the table's columns themselves are reserved for the
 
1521
"automatic" generation of bind names.  We can combine the usage
 
1522
of implicitly available bind names and explicitly named parameters
 
1523
as in the example below:
 
1524
 
 
1525
.. sourcecode:: pycon+sql
 
1526
 
 
1527
    >>> stmt = users.insert().\
 
1528
    ...         values(name=bindparam('_name') + " .. name")
 
1529
    >>> conn.execute(stmt, [               # doctest: +ELLIPSIS
 
1530
    ...        {'id':4, '_name':'name1'},
 
1531
    ...        {'id':5, '_name':'name2'},
 
1532
    ...        {'id':6, '_name':'name3'},
 
1533
    ...     ])
 
1534
    {opensql}INSERT INTO users (id, name) VALUES (?, (? || ?))
 
1535
    ((4, 'name1', ' .. name'), (5, 'name2', ' .. name'), (6, 'name3', ' .. name'))
 
1536
    COMMIT
 
1537
    <sqlalchemy.engine.result.ResultProxy object at 0x...>
 
1538
 
 
1539
An UPDATE statement is emitted using the :meth:`~.TableClause.update` construct.  This
 
1540
works much like an INSERT, except there is an additional WHERE clause
1405
1541
that can be specified:
1406
1542
 
1407
1543
.. sourcecode:: pycon+sql
1408
1544
 
1409
 
    >>> # change 'jack' to 'ed'
1410
 
    {sql}>>> conn.execute(users.update().
1411
 
    ...                    where(users.c.name=='jack').
1412
 
    ...                    values(name='ed')
1413
 
    ...                ) #doctest: +ELLIPSIS
1414
 
    UPDATE users SET name=? WHERE users.name = ?
 
1545
    >>> stmt = users.update().\
 
1546
    ...             where(users.c.name == 'jack').\
 
1547
    ...             values(name='ed')
 
1548
 
 
1549
    >>> conn.execute(stmt) #doctest: +ELLIPSIS
 
1550
    {opensql}UPDATE users SET name=? WHERE users.name = ?
1415
1551
    ('ed', 'jack')
1416
1552
    COMMIT
1417
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
1418
 
 
1419
 
    >>> # use bind parameters
1420
 
    >>> u = users.update().\
1421
 
    ...             where(users.c.name==bindparam('oldname')).\
 
1553
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
 
1554
 
 
1555
When using :meth:`~.TableClause.update` in an "execute many" context,
 
1556
we may wish to also use explicitly named bound parameters in the
 
1557
WHERE clause.  Again, :func:`~.expression.bindparam` is the construct
 
1558
used to achieve this:
 
1559
 
 
1560
.. sourcecode:: pycon+sql
 
1561
 
 
1562
    >>> stmt = users.update().\
 
1563
    ...             where(users.c.name == bindparam('oldname')).\
1422
1564
    ...             values(name=bindparam('newname'))
1423
 
    {sql}>>> conn.execute(u, oldname='jack', newname='ed') #doctest: +ELLIPSIS
1424
 
    UPDATE users SET name=? WHERE users.name = ?
1425
 
    ('ed', 'jack')
1426
 
    COMMIT
1427
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
1428
 
 
1429
 
    >>> # with binds, you can also update many rows at once
1430
 
    {sql}>>> conn.execute(u,
 
1565
    >>> conn.execute(stmt, [
1431
1566
    ...     {'oldname':'jack', 'newname':'ed'},
1432
1567
    ...     {'oldname':'wendy', 'newname':'mary'},
1433
1568
    ...     {'oldname':'jim', 'newname':'jake'},
1434
 
    ...     ) #doctest: +ELLIPSIS
1435
 
    UPDATE users SET name=? WHERE users.name = ?
1436
 
    [('ed', 'jack'), ('mary', 'wendy'), ('jake', 'jim')]
 
1569
    ...     ]) #doctest: +ELLIPSIS
 
1570
    {opensql}UPDATE users SET name=? WHERE users.name = ?
 
1571
    (('ed', 'jack'), ('mary', 'wendy'), ('jake', 'jim'))
1437
1572
    COMMIT
1438
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
1573
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
1439
1574
 
1440
 
    >>> # update a column to an expression.:
1441
 
    {sql}>>> conn.execute(users.update().
1442
 
    ...                     values(fullname="Fullname: " + users.c.name)
1443
 
    ...                 ) #doctest: +ELLIPSIS
1444
 
    UPDATE users SET fullname=(? || users.name)
1445
 
    ('Fullname: ',)
1446
 
    COMMIT
1447
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
1448
1575
 
1449
1576
Correlated Updates
1450
1577
------------------
1454
1581
 
1455
1582
.. sourcecode:: pycon+sql
1456
1583
 
1457
 
    >>> s = select([addresses.c.email_address], addresses.c.user_id==users.c.id).limit(1)
1458
 
    {sql}>>> conn.execute(users.update().values(fullname=s)) #doctest: +ELLIPSIS,+NORMALIZE_WHITESPACE
1459
 
    UPDATE users SET fullname=(SELECT addresses.email_address
1460
 
    FROM addresses
1461
 
    WHERE addresses.user_id = users.id
1462
 
    LIMIT 1 OFFSET 0)
1463
 
    ()
 
1584
    >>> stmt = select([addresses.c.email_address]).\
 
1585
    ...             where(addresses.c.user_id == users.c.id).\
 
1586
    ...             limit(1)
 
1587
    >>> conn.execute(users.update().values(fullname=stmt)) #doctest: +ELLIPSIS,+NORMALIZE_WHITESPACE
 
1588
    {opensql}UPDATE users SET fullname=(SELECT addresses.email_address
 
1589
        FROM addresses
 
1590
        WHERE addresses.user_id = users.id
 
1591
        LIMIT ? OFFSET ?)
 
1592
    (1, 0)
1464
1593
    COMMIT
1465
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
1594
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
1466
1595
 
1467
1596
Multiple Table Updates
1468
1597
----------------------
1479
1608
 
1480
1609
    stmt = users.update().\
1481
1610
            values(name='ed wood').\
1482
 
            where(users.c.id==addresses.c.id).\
 
1611
            where(users.c.id == addresses.c.id).\
1483
1612
            where(addresses.c.email_address.startswith('ed%'))
1484
1613
    conn.execute(stmt)
1485
1614
 
1497
1626
                users.c.name:'ed wood',
1498
1627
                addresses.c.email_address:'ed.wood@foo.com'
1499
1628
            }).\
1500
 
            where(users.c.id==addresses.c.id).\
 
1629
            where(users.c.id == addresses.c.id).\
1501
1630
            where(addresses.c.email_address.startswith('ed%'))
1502
1631
 
1503
1632
The tables are referenced explicitly in the SET clause::
1514
1643
.. _deletes:
1515
1644
 
1516
1645
Deletes
1517
 
========
 
1646
-------
1518
1647
 
1519
1648
Finally, a delete.  This is accomplished easily enough using the
1520
 
:func:`~.expression.delete` construct:
 
1649
:meth:`~.TableClause.delete` construct:
1521
1650
 
1522
1651
.. sourcecode:: pycon+sql
1523
1652
 
1524
 
    {sql}>>> conn.execute(addresses.delete()) #doctest: +ELLIPSIS
1525
 
    DELETE FROM addresses
 
1653
    >>> conn.execute(addresses.delete()) #doctest: +ELLIPSIS
 
1654
    {opensql}DELETE FROM addresses
1526
1655
    ()
1527
1656
    COMMIT
1528
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
1657
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
1529
1658
 
1530
 
    {sql}>>> conn.execute(users.delete().where(users.c.name > 'm')) #doctest: +ELLIPSIS
1531
 
    DELETE FROM users WHERE users.name > ?
 
1659
    >>> conn.execute(users.delete().where(users.c.name > 'm')) #doctest: +ELLIPSIS
 
1660
    {opensql}DELETE FROM users WHERE users.name > ?
1532
1661
    ('m',)
1533
1662
    COMMIT
1534
 
    {stop}<sqlalchemy.engine.base.ResultProxy object at 0x...>
 
1663
    {stop}<sqlalchemy.engine.result.ResultProxy object at 0x...>
 
1664
 
 
1665
Matched Row Counts
 
1666
------------------
 
1667
 
 
1668
Both of :meth:`~.TableClause.update` and
 
1669
:meth:`~.TableClause.delete` are associated with *matched row counts*.  This is a
 
1670
number indicating the number of rows that were matched by the WHERE clause.
 
1671
Note that by "matched", this includes rows where no UPDATE actually took place.
 
1672
The value is available as :attr:`~.ResultProxy.rowcount`:
 
1673
 
 
1674
.. sourcecode:: pycon+sql
 
1675
 
 
1676
    >>> result = conn.execute(users.delete()) #doctest: +ELLIPSIS
 
1677
    {opensql}DELETE FROM users
 
1678
    ()
 
1679
    COMMIT
 
1680
    {stop}>>> result.rowcount
 
1681
    1
1535
1682
 
1536
1683
Further Reference
1537
1684
==================
1540
1687
 
1541
1688
Database Metadata Reference: :ref:`metadata_toplevel`
1542
1689
 
1543
 
Engine Reference: :ref:`engines_toplevel`
 
1690
Engine Reference: :doc:`/core/engines`
1544
1691
 
1545
1692
Connection Reference: :ref:`connections_toplevel`
1546
1693