662
650
<div class="highlight-python"><div class="highlight"><pre><span class="n">somecolumn</span><span class="o">.</span><span class="n">op</span><span class="p">(</span><span class="s">'&'</span><span class="p">)(</span><span class="mh">0xff</span><span class="p">)</span></pre></div>
664
652
<p>is a bitwise AND of the value in <cite>somecolumn</cite>.</p>
653
<div class="section" id="operator-customization">
654
<h3>Operator Customization<a class="headerlink" href="#operator-customization" title="Permalink to this headline">¶</a></h3>
655
<p>While <a class="reference internal" href="expression_api.html#sqlalchemy.sql.operators.ColumnOperators.op" title="sqlalchemy.sql.operators.ColumnOperators.op"><tt class="xref py py-meth docutils literal"><span class="pre">ColumnOperators.op()</span></tt></a> is handy to get at a custom operator in a hurry,
656
the Core supports fundamental customization and extension of the operator system at
657
the type level. The behavior of existing operators can be modified on a per-type
658
basis, and new operations can be defined which become available for all column
659
expressions that are part of that particular type. See the section <a class="reference internal" href="types.html#types-operators"><em>Redefining and Creating New Operators</em></a>
660
for a description.</p>
666
663
<div class="section" id="conjunctions">
667
664
<h2>Conjunctions<a class="headerlink" href="#conjunctions" title="Permalink to this headline">¶</a></h2>
668
665
<p>We’d like to show off some of our operators inside of <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a>
669
666
constructs. But we need to lump them together a little more, so let’s first
670
667
introduce some conjunctions. Conjunctions are those little words like AND and
671
OR that put things together. We’ll also hit upon NOT. AND, OR and NOT can work
668
OR that put things together. We’ll also hit upon NOT. <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.and_" title="sqlalchemy.sql.expression.and_"><tt class="xref py py-func docutils literal"><span class="pre">and_()</span></tt></a>, <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.or_" title="sqlalchemy.sql.expression.or_"><tt class="xref py py-func docutils literal"><span class="pre">or_()</span></tt></a>,
669
and <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.not_" title="sqlalchemy.sql.expression.not_"><tt class="xref py py-func docutils literal"><span class="pre">not_()</span></tt></a> can work
672
670
from the corresponding functions SQLAlchemy provides (notice we also throw in
671
a <a class="reference internal" href="expression_api.html#sqlalchemy.sql.operators.ColumnOperators.like" title="sqlalchemy.sql.operators.ColumnOperators.like"><tt class="xref py py-meth docutils literal"><span class="pre">like()</span></tt></a>):</p>
674
672
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">sqlalchemy.sql</span> <span class="kn">import</span> <span class="n">and_</span><span class="p">,</span> <span class="n">or_</span><span class="p">,</span> <span class="n">not_</span>
675
<span class="gp">>>> </span><span class="k">print</span> <span class="n">and_</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'j%'</span><span class="p">),</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
676
<span class="gp">... </span> <span class="n">or_</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">==</span><span class="s">'wendy@aol.com'</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">==</span><span class="s">'jack@yahoo.com'</span><span class="p">),</span>
677
<span class="gp">... </span> <span class="n">not_</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">></span><span class="mi">5</span><span class="p">))</span>
673
<span class="gp">>>> </span><span class="k">print</span> <span class="n">and_</span><span class="p">(</span>
674
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'j%'</span><span class="p">),</span>
675
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
676
<span class="gp">... </span> <span class="n">or_</span><span class="p">(</span>
677
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span> <span class="o">==</span> <span class="s">'wendy@aol.com'</span><span class="p">,</span>
678
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span> <span class="o">==</span> <span class="s">'jack@yahoo.com'</span>
679
<span class="gp">... </span> <span class="p">),</span>
680
<span class="gp">... </span> <span class="n">not_</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">></span> <span class="mi">5</span><span class="p">)</span>
681
<span class="gp">... </span> <span class="p">)</span>
678
682
<span class="go">users.name LIKE :name_1 AND users.id = addresses.user_id AND</span>
679
<span class="go">(addresses.email_address = :email_address_1 OR addresses.email_address = :email_address_2)</span>
683
<span class="go">(addresses.email_address = :email_address_1</span>
684
<span class="go"> OR addresses.email_address = :email_address_2)</span>
680
685
<span class="go">AND users.id <= :id_1</span></pre></div>
682
687
<p>And you can also use the re-jiggered bitwise AND, OR and NOT operators,
683
688
although because of Python operator precedence you have to watch your
685
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">print</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'j%'</span><span class="p">)</span> <span class="o">&</span> <span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span> <span class="o">&</span> \
686
<span class="gp">... </span> <span class="p">((</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">==</span><span class="s">'wendy@aol.com'</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">==</span><span class="s">'jack@yahoo.com'</span><span class="p">))</span> \
690
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">print</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'j%'</span><span class="p">)</span> <span class="o">&</span> <span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span> <span class="o">&</span> \
691
<span class="gp">... </span> <span class="p">(</span>
692
<span class="gp">... </span> <span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span> <span class="o">==</span> <span class="s">'wendy@aol.com'</span><span class="p">)</span> <span class="o">|</span> \
693
<span class="gp">... </span> <span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span> <span class="o">==</span> <span class="s">'jack@yahoo.com'</span><span class="p">)</span>
694
<span class="gp">... </span> <span class="p">)</span> \
687
695
<span class="gp">... </span> <span class="o">&</span> <span class="o">~</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">></span><span class="mi">5</span><span class="p">)</span>
688
696
<span class="go">users.name LIKE :name_1 AND users.id = addresses.user_id AND</span>
689
<span class="go">(addresses.email_address = :email_address_1 OR addresses.email_address = :email_address_2)</span>
697
<span class="go">(addresses.email_address = :email_address_1</span>
698
<span class="go"> OR addresses.email_address = :email_address_2)</span>
690
699
<span class="go">AND users.id <= :id_1</span></pre></div>
692
701
<p>So with all of this vocabulary, let’s select all users who have an email
693
702
address at AOL or MSN, whose name starts with a letter between “m” and “z”,
694
703
and we’ll also generate a column containing their full name combined with
695
704
their email address. We will add two new constructs to this statement,
696
<tt class="docutils literal"><span class="pre">between()</span></tt> and <tt class="docutils literal"><span class="pre">label()</span></tt>. <tt class="docutils literal"><span class="pre">between()</span></tt> produces a BETWEEN clause, and
697
<tt class="docutils literal"><span class="pre">label()</span></tt> is used in a column expression to produce labels using the <tt class="docutils literal"><span class="pre">AS</span></tt>
705
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.operators.ColumnOperators.between" title="sqlalchemy.sql.operators.ColumnOperators.between"><tt class="xref py py-meth docutils literal"><span class="pre">between()</span></tt></a> and <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ColumnElement.label" title="sqlalchemy.sql.expression.ColumnElement.label"><tt class="xref py py-meth docutils literal"><span class="pre">label()</span></tt></a>.
706
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.operators.ColumnOperators.between" title="sqlalchemy.sql.operators.ColumnOperators.between"><tt class="xref py py-meth docutils literal"><span class="pre">between()</span></tt></a> produces a BETWEEN clause, and
707
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ColumnElement.label" title="sqlalchemy.sql.expression.ColumnElement.label"><tt class="xref py py-meth docutils literal"><span class="pre">label()</span></tt></a> is used in a column expression to produce labels using the <tt class="docutils literal"><span class="pre">AS</span></tt>
698
708
keyword; it’s recommended when selecting from expressions that otherwise would
699
709
not have a name:</p>
700
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">fullname</span> <span class="o">+</span> <span class="s">", "</span> <span class="o">+</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">)</span><span class="o">.</span><span class="n">label</span><span class="p">(</span><span class="s">'title'</span><span class="p">)],</span>
701
<span class="gp">... </span> <span class="n">and_</span><span class="p">(</span>
702
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
703
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">between</span><span class="p">(</span><span class="s">'m'</span><span class="p">,</span> <span class="s">'z'</span><span class="p">),</span>
704
<span class="gp">... </span> <span class="n">or_</span><span class="p">(</span>
705
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@aol.com'</span><span class="p">),</span>
706
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@msn.com'</span><span class="p">)</span>
710
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">fullname</span> <span class="o">+</span>
711
<span class="gp">... </span> <span class="s">", "</span> <span class="o">+</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">)</span><span class="o">.</span>
712
<span class="gp">... </span> <span class="n">label</span><span class="p">(</span><span class="s">'title'</span><span class="p">)])</span><span class="o">.</span>\
713
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span>
714
<span class="gp">... </span> <span class="n">and_</span><span class="p">(</span>
715
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
716
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">between</span><span class="p">(</span><span class="s">'m'</span><span class="p">,</span> <span class="s">'z'</span><span class="p">),</span>
717
<span class="gp">... </span> <span class="n">or_</span><span class="p">(</span>
718
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@aol.com'</span><span class="p">),</span>
719
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@msn.com'</span><span class="p">)</span>
720
<span class="gp">... </span> <span class="p">)</span>
707
721
<span class="gp">... </span> <span class="p">)</span>
708
722
<span class="gp">... </span> <span class="p">)</span>
709
<span class="gp">... </span> <span class="p">)</span>
710
<span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
723
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
711
724
<span class="go">SELECT users.fullname || ? || addresses.email_address AS title</span>
712
725
<span class="go">FROM users, addresses</span>
713
726
<span class="go">WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND</span>
719
732
it will determine the FROM clause based on all of its other bits; the columns
720
733
clause, the where clause, and also some other elements which we haven’t
721
734
covered yet, which include ORDER BY, GROUP BY, and HAVING.</p>
735
<p>A shortcut to using <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.and_" title="sqlalchemy.sql.expression.and_"><tt class="xref py py-func docutils literal"><span class="pre">and_()</span></tt></a> is to chain together multiple
736
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.where" title="sqlalchemy.sql.expression.Select.where"><tt class="xref py py-meth docutils literal"><span class="pre">where()</span></tt></a> clauses. The above can also be written as:</p>
737
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">fullname</span> <span class="o">+</span>
738
<span class="gp">... </span> <span class="s">", "</span> <span class="o">+</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">)</span><span class="o">.</span>
739
<span class="gp">... </span> <span class="n">label</span><span class="p">(</span><span class="s">'title'</span><span class="p">)])</span><span class="o">.</span>\
740
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span>\
741
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">between</span><span class="p">(</span><span class="s">'m'</span><span class="p">,</span> <span class="s">'z'</span><span class="p">))</span><span class="o">.</span>\
742
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span>
743
<span class="gp">... </span> <span class="n">or_</span><span class="p">(</span>
744
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@aol.com'</span><span class="p">),</span>
745
<span class="gp">... </span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@msn.com'</span><span class="p">)</span>
746
<span class="gp">... </span> <span class="p">)</span>
747
<span class="gp">... </span> <span class="p">)</span>
748
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
749
<span class="go">SELECT users.fullname || ? || addresses.email_address AS title</span>
750
<span class="go">FROM users, addresses</span>
751
<span class="go">WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND</span>
752
<span class="go">(addresses.email_address LIKE ? OR addresses.email_address LIKE ?)</span>
753
<span class="go">(', ', 'm', 'z', '%@aol.com', '%@msn.com')</span>
754
<span class="go">[(u'Wendy Williams, wendy@aol.com',)]</span></pre></div>
756
<p>The way that we can build up a <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct through successive
757
method calls is called <a class="reference internal" href="../glossary.html#term-method-chaining"><em class="xref std std-term">method chaining</em></a>.</p>
723
759
<div class="section" id="using-text">
724
760
<span id="sqlexpression-text"></span><h2>Using Text<a class="headerlink" href="#using-text" title="Permalink to this headline">¶</a></h2>
725
761
<p>Our last example really became a handful to type. Going from what one
726
762
understands to be a textual SQL expression into a Python construct which
727
763
groups components together in a programmatic style can be hard. That’s why
728
SQLAlchemy lets you just use strings too. The <tt class="docutils literal"><span class="pre">text()</span></tt> construct represents
729
any textual statement. To use bind parameters with <tt class="docutils literal"><span class="pre">text()</span></tt>, always use the
730
named colon format. Such as below, we create a <tt class="docutils literal"><span class="pre">text()</span></tt> and execute it,
731
feeding in the bind parameters to the <tt class="docutils literal"><span class="pre">execute()</span></tt> method:</p>
764
SQLAlchemy lets you just use strings too. The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.text" title="sqlalchemy.sql.expression.text"><tt class="xref py py-func docutils literal"><span class="pre">text()</span></tt></a> construct represents
765
any textual statement, in a backend-agnostic way.
766
To use bind parameters with <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.text" title="sqlalchemy.sql.expression.text"><tt class="xref py py-func docutils literal"><span class="pre">text()</span></tt></a>, always use the
767
named colon format. Such as below, we create a <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.text" title="sqlalchemy.sql.expression.text"><tt class="xref py py-func docutils literal"><span class="pre">text()</span></tt></a> and execute it,
768
feeding in the bind parameters to the <a class="reference internal" href="connections.html#sqlalchemy.engine.Connection.execute" title="sqlalchemy.engine.Connection.execute"><tt class="xref py py-meth docutils literal"><span class="pre">execute()</span></tt></a> method:</p>
732
769
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">sqlalchemy.sql</span> <span class="kn">import</span> <span class="n">text</span>
733
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">text</span><span class="p">(</span><span class="s">"""SELECT users.fullname || ', ' || addresses.email_address AS title</span>
734
<span class="gp">... </span> <span class="n">FROM</span> <span class="n">users</span><span class="p">,</span> <span class="n">addresses</span>
735
<span class="gp">... </span> <span class="n">WHERE</span> <span class="n">users</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">addresses</span><span class="o">.</span><span class="n">user_id</span> <span class="n">AND</span> <span class="n">users</span><span class="o">.</span><span class="n">name</span> <span class="n">BETWEEN</span> <span class="p">:</span><span class="n">x</span> <span class="n">AND</span> <span class="p">:</span><span class="n">y</span> <span class="n">AND</span>
736
<span class="gp">... </span> <span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">email_address</span> <span class="n">LIKE</span> <span class="p">:</span><span class="n">e1</span> <span class="n">OR</span> <span class="n">addresses</span><span class="o">.</span><span class="n">email_address</span> <span class="n">LIKE</span> <span class="p">:</span><span class="n">e2</span><span class="p">)</span>
737
<span class="gp">... </span> <span class="s">""")</span>
738
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="s">'m'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="s">'z'</span><span class="p">,</span> <span class="n">e1</span><span class="o">=</span><span class="s">'%@aol.com'</span><span class="p">,</span> <span class="n">e2</span><span class="o">=</span><span class="s">'%@msn.com'</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
770
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">text</span><span class="p">(</span>
771
<span class="gp">... </span> <span class="s">"SELECT users.fullname || ', ' || addresses.email_address AS title "</span>
772
<span class="gp">... </span> <span class="s">"FROM users, addresses "</span>
773
<span class="gp">... </span> <span class="s">"WHERE users.id = addresses.user_id "</span>
774
<span class="gp">... </span> <span class="s">"AND users.name BETWEEN :x AND :y "</span>
775
<span class="gp">... </span> <span class="s">"AND (addresses.email_address LIKE :e1 "</span>
776
<span class="gp">... </span> <span class="s">"OR addresses.email_address LIKE :e2)"</span><span class="p">)</span>
777
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="s">'m'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="s">'z'</span><span class="p">,</span> <span class="n">e1</span><span class="o">=</span><span class="s">'%@aol.com'</span><span class="p">,</span> <span class="n">e2</span><span class="o">=</span><span class="s">'%@msn.com'</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
739
778
<div class='popup_sql'>SELECT users.fullname || ', ' || addresses.email_address AS title
740
779
FROM users, addresses
741
780
WHERE users.id = addresses.user_id AND users.name BETWEEN ? AND ? AND
742
781
(addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
743
782
('m', 'z', '%@aol.com', '%@msn.com')</div><span class="go">[(u'Wendy Williams, wendy@aol.com',)]</span></pre></div>
745
<p>To gain a “hybrid” approach, the <cite>select()</cite> construct accepts strings for most
784
<p>To gain a “hybrid” approach, the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct accepts strings for most
746
785
of its arguments. Below we combine the usage of strings with our constructed
747
786
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> object, by using the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> object to structure the
748
787
statement, and strings to provide all the content within the structure. For
749
788
this example, SQLAlchemy is not given any <a class="reference internal" href="schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a>
750
789
or <a class="reference internal" href="schema.html#sqlalchemy.schema.Table" title="sqlalchemy.schema.Table"><tt class="xref py py-class docutils literal"><span class="pre">Table</span></tt></a> objects in any of its expressions, so it
751
cannot generate a FROM clause. So we also give it the <tt class="docutils literal"><span class="pre">from_obj</span></tt> keyword
752
argument, which is a list of <tt class="docutils literal"><span class="pre">ClauseElements</span></tt> (or strings) to be placed
753
within the FROM clause:</p>
754
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="s">"users.fullname || ', ' || addresses.email_address AS title"</span><span class="p">],</span>
755
<span class="gp">... </span> <span class="n">and_</span><span class="p">(</span>
756
<span class="gp">... </span> <span class="s">"users.id = addresses.user_id"</span><span class="p">,</span>
757
<span class="gp">... </span> <span class="s">"users.name BETWEEN 'm' AND 'z'"</span><span class="p">,</span>
758
<span class="gp">... </span> <span class="s">"(addresses.email_address LIKE :x OR addresses.email_address LIKE :y)"</span>
759
<span class="gp">... </span> <span class="p">),</span>
760
<span class="gp">... </span> <span class="n">from_obj</span><span class="o">=</span><span class="p">[</span><span class="s">'users'</span><span class="p">,</span> <span class="s">'addresses'</span><span class="p">]</span>
761
<span class="gp">... </span> <span class="p">)</span>
762
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="s">'%@aol.com'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="s">'%@msn.com'</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
790
cannot generate a FROM clause. So we also use the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.select_from" title="sqlalchemy.sql.expression.Select.select_from"><tt class="xref py py-meth docutils literal"><span class="pre">select_from()</span></tt></a>
791
method, which accepts a <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.FromClause" title="sqlalchemy.sql.expression.FromClause"><tt class="xref py py-class docutils literal"><span class="pre">FromClause</span></tt></a> or string expression
792
to be placed within the FROM clause:</p>
793
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span>
794
<span class="gp">... </span> <span class="s">"users.fullname || ', ' || addresses.email_address AS title"</span>
795
<span class="gp">... </span> <span class="p">])</span><span class="o">.</span>\
796
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span>
797
<span class="gp">... </span> <span class="n">and_</span><span class="p">(</span>
798
<span class="gp">... </span> <span class="s">"users.id = addresses.user_id"</span><span class="p">,</span>
799
<span class="gp">... </span> <span class="s">"users.name BETWEEN 'm' AND 'z'"</span><span class="p">,</span>
800
<span class="gp">... </span> <span class="s">"(addresses.email_address LIKE :x OR addresses.email_address LIKE :y)"</span>
801
<span class="gp">... </span> <span class="p">)</span>
802
<span class="gp">... </span> <span class="p">)</span><span class="o">.</span><span class="n">select_from</span><span class="p">(</span><span class="s">'users, addresses'</span><span class="p">)</span>
803
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="s">'%@aol.com'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="s">'%@msn.com'</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
763
804
<div class='popup_sql'>SELECT users.fullname || ', ' || addresses.email_address AS title
764
805
FROM users, addresses
765
WHERE users.id = addresses.user_id AND users.name BETWEEN 'm' AND 'z' AND (addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
806
WHERE users.id = addresses.user_id AND users.name BETWEEN 'm' AND 'z'
807
AND (addresses.email_address LIKE ? OR addresses.email_address LIKE ?)
766
808
('%@aol.com', '%@msn.com')</div><span class="go">[(u'Wendy Williams, wendy@aol.com',)]</span></pre></div>
768
810
<p>Going from constructed SQL to text, we lose some capabilities. We lose the
896
949
<p>If you don’t know what that SQL means, don’t worry ! The secret tribe of
897
950
Oracle DBAs don’t want their black magic being found out ;).</p>
899
<div class="section" id="intro-to-generative-selects">
900
<h2>Intro to Generative Selects<a class="headerlink" href="#intro-to-generative-selects" title="Permalink to this headline">¶</a></h2>
901
<p>We’ve now gained the ability to construct very sophisticated statements. We
902
can use all kinds of operators, table constructs, text, joins, and aliases.
903
The point of all of this, as mentioned earlier, is not that it’s an “easier”
904
or “better” way to write SQL than just writing a SQL statement yourself; the
905
point is that it’s better for writing <em>programmatically generated</em> SQL which
906
can be morphed and adapted as needed in automated scenarios.</p>
907
<p>To support this, the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct we’ve been working with
908
supports piecemeal construction, in addition to the “all at once” method we’ve
909
been doing. Suppose you’re writing a search function, which receives criterion
910
and then must construct a select from it. To accomplish this, upon each
911
criterion encountered, you apply “generative” criterion to an existing
912
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct with new elements, one at a time. We start with a
913
basic <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> constructed with the shortcut method available on the
914
<tt class="docutils literal"><span class="pre">users</span></tt> table:</p>
915
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">select</span><span class="p">()</span>
916
<span class="gp">>>> </span><span class="k">print</span> <span class="n">query</span>
917
<span class="go">SELECT users.id, users.name, users.fullname</span>
918
<span class="go">FROM users</span></pre></div>
920
<p>We encounter search criterion of “name=’jack’”. So we apply WHERE criterion
922
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">==</span><span class="s">'jack'</span><span class="p">)</span></pre></div>
924
<p>Next, we encounter that they’d like the results in descending order by full
925
name. We apply ORDER BY, using an extra modifier <tt class="docutils literal"><span class="pre">desc</span></tt>:</p>
926
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">fullname</span><span class="o">.</span><span class="n">desc</span><span class="p">())</span></pre></div>
928
<p>We also come across that they’d like only users who have an address at MSN. A
929
quick way to tack this on is by using an EXISTS clause, which we correlate to
930
the <tt class="docutils literal"><span class="pre">users</span></tt> table in the enclosing SELECT:</p>
931
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">sqlalchemy.sql</span> <span class="kn">import</span> <span class="n">exists</span>
932
<span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">where</span><span class="p">(</span>
933
<span class="gp">... </span> <span class="n">exists</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">],</span>
934
<span class="gp">... </span> <span class="n">and_</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="o">==</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">like</span><span class="p">(</span><span class="s">'%@msn.com'</span><span class="p">))</span>
935
<span class="gp">... </span> <span class="p">)</span><span class="o">.</span><span class="n">correlate</span><span class="p">(</span><span class="n">users</span><span class="p">))</span></pre></div>
937
<p>And finally, the application also wants to see the listing of email addresses
938
at once; so to save queries, we outerjoin the <tt class="docutils literal"><span class="pre">addresses</span></tt> table (using an
939
outer join so that users with no addresses come back as well; since we’re
940
programmatic, we might not have kept track that we used an EXISTS clause
941
against the <tt class="docutils literal"><span class="pre">addresses</span></tt> table too...). Additionally, since the <tt class="docutils literal"><span class="pre">users</span></tt> and
942
<tt class="docutils literal"><span class="pre">addresses</span></tt> table both have a column named <tt class="docutils literal"><span class="pre">id</span></tt>, let’s isolate their names
943
from each other in the COLUMNS clause by using labels:</p>
944
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">column</span><span class="p">(</span><span class="n">addresses</span><span class="p">)</span><span class="o">.</span><span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span><span class="n">apply_labels</span><span class="p">()</span></pre></div>
946
<p>Let’s bake for .0001 seconds and see what rises:</p>
947
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">query</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
948
<div class='show_sql'>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
949
FROM users LEFT OUTER JOIN addresses ON users.id = addresses.user_id
950
WHERE users.name = ? AND (EXISTS (SELECT addresses.id
952
WHERE addresses.user_id = users.id AND addresses.email_address LIKE ?)) ORDER BY users.fullname DESC
953
('jack', '%@msn.com')</div><span class="go">[(1, u'jack', u'Jack Jones', 1, 1, u'jack@yahoo.com'), (1, u'jack', u'Jack Jones', 2, 1, u'jack@msn.com')]</span></pre></div>
955
<p>The generative approach is about starting small, adding one thing at a time,
956
to arrive with a full statement.</p>
957
<div class="section" id="transforming-a-statement">
958
<h3>Transforming a Statement<a class="headerlink" href="#transforming-a-statement" title="Permalink to this headline">¶</a></h3>
959
<p>We’ve seen how methods like <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.where" title="sqlalchemy.sql.expression.Select.where"><tt class="xref py py-meth docutils literal"><span class="pre">Select.where()</span></tt></a> and <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression._SelectBase.order_by" title="sqlalchemy.sql.expression._SelectBase.order_by"><tt class="xref py py-meth docutils literal"><span class="pre">_SelectBase.order_by()</span></tt></a> are
960
part of the so-called <em>Generative</em> family of methods on the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct,
961
where one <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> copies itself to return a new one with modifications.
962
SQL constructs also support another form of generative behavior which is
963
the <em>transformation</em>. This is an advanced technique that most core applications
964
won’t use directly; however, it is a system which the ORM relies on heavily,
965
and can be useful for any system that deals with generalized behavior of Core SQL
967
<p>Using a transformation we can take our <tt class="docutils literal"><span class="pre">users</span></tt>/<tt class="docutils literal"><span class="pre">addresses</span></tt> query and replace
968
all occurrences of <tt class="docutils literal"><span class="pre">addresses</span></tt> with an alias of itself. That is, anywhere
969
that <tt class="docutils literal"><span class="pre">addresses</span></tt> is referred to in the original query, the new query will
970
refer to <tt class="docutils literal"><span class="pre">addresses_1</span></tt>, which is selected as <tt class="docutils literal"><span class="pre">addresses</span> <span class="pre">AS</span> <span class="pre">addresses_1</span></tt>.
971
The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.FromClause.replace_selectable" title="sqlalchemy.sql.expression.FromClause.replace_selectable"><tt class="xref py py-meth docutils literal"><span class="pre">FromClause.replace_selectable()</span></tt></a> method can achieve this:</p>
972
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">a1</span> <span class="o">=</span> <span class="n">addresses</span><span class="o">.</span><span class="n">alias</span><span class="p">()</span>
973
<span class="gp">>>> </span><span class="n">query</span> <span class="o">=</span> <span class="n">query</span><span class="o">.</span><span class="n">replace_selectable</span><span class="p">(</span><span class="n">addresses</span><span class="p">,</span> <span class="n">a1</span><span class="p">)</span>
974
<span class="gp">>>> </span><span class="k">print</span> <span class="n">query</span>
975
<div class='show_sql'>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
976
FROM users LEFT OUTER JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id
977
WHERE users.name = :name_1 AND (EXISTS (SELECT addresses_1.id
978
FROM addresses AS addresses_1
979
WHERE addresses_1.user_id = users.id AND addresses_1.email_address LIKE :email_address_1)) ORDER BY users.fullname DESC</div></pre></div>
981
<p>For a query such as the above, we can access the columns referred
982
to by the <tt class="docutils literal"><span class="pre">a1</span></tt> alias in a result set using the <a class="reference internal" href="schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a> objects
983
present directly on <tt class="docutils literal"><span class="pre">a1</span></tt>:</p>
984
<div class="highlight-pycon+sql"><div class="highlight"><pre><a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">query</span><span class="p">):</span>
985
<span class="gp">... </span> <span class="k">print</span> <span class="s">"Name:"</span><span class="p">,</span> <span class="n">row</span><span class="p">[</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">],</span> <span class="s">"; Email Address"</span><span class="p">,</span> <span class="n">row</span><span class="p">[</span><span class="n">a1</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">]</span>
986
<div class='popup_sql'>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
987
FROM users LEFT OUTER JOIN addresses AS addresses_1 ON users.id = addresses_1.user_id
988
WHERE users.name = ? AND (EXISTS (SELECT addresses_1.id
989
FROM addresses AS addresses_1
990
WHERE addresses_1.user_id = users.id AND addresses_1.email_address LIKE ?)) ORDER BY users.fullname DESC
991
('jack', '%@msn.com')</div><span class="go">Name: jack ; Email Address jack@yahoo.com</span>
992
<span class="go">Name: jack ; Email Address jack@msn.com</span></pre></div>
996
952
<div class="section" id="everything-else">
997
953
<h2>Everything Else<a class="headerlink" href="#everything-else" title="Permalink to this headline">¶</a></h2>
998
954
<p>The concepts of creating SQL expressions have been introduced. What’s left are
1186
1180
<div class="section" id="scalar-selects">
1187
<h3>Scalar Selects<a class="headerlink" href="#scalar-selects" title="Permalink to this headline">¶</a></h3>
1188
<p>To embed a SELECT in a column expression, use
1189
<tt class="xref py py-func docutils literal"><span class="pre">as_scalar()</span></tt>:</p>
1190
<div class="highlight-pycon+sql"><div class="highlight"><pre><a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">select</span><span class="p">([</span>
1191
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
1192
<span class="gp">... </span> <span class="n">select</span><span class="p">([</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)],</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span><span class="n">as_scalar</span><span class="p">()</span>
1193
<span class="gp">... </span> <span class="p">]))</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1194
<div class='popup_sql'>SELECT users.name, (SELECT count(addresses.id) AS count_1
1181
<span id="id1"></span><h3>Scalar Selects<a class="headerlink" href="#scalar-selects" title="Permalink to this headline">¶</a></h3>
1182
<p>A scalar select is a SELECT that returns exactly one row and one
1183
column. It can then be used as a column expression. A scalar select
1184
is often a <a class="reference internal" href="../glossary.html#term-correlated-subquery"><em class="xref std std-term">correlated subquery</em></a>, which relies upon the enclosing
1185
SELECT statement in order to acquire at least one of its FROM clauses.</p>
1186
<p>The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> construct can be modified to act as a
1187
column expression by calling either the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.SelectBase.as_scalar" title="sqlalchemy.sql.expression.SelectBase.as_scalar"><tt class="xref py py-meth docutils literal"><span class="pre">as_scalar()</span></tt></a>
1188
or <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.SelectBase.label" title="sqlalchemy.sql.expression.SelectBase.label"><tt class="xref py py-meth docutils literal"><span class="pre">label()</span></tt></a> method:</p>
1189
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)])</span><span class="o">.</span>\
1190
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span>\
1191
<span class="gp">... </span> <span class="n">as_scalar</span><span class="p">()</span></pre></div>
1193
<p>The above construct is now a <tt class="xref py py-class docutils literal"><span class="pre">ScalarSelect</span></tt> object,
1194
and is no longer part of the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.FromClause" title="sqlalchemy.sql.expression.FromClause"><tt class="xref py py-class docutils literal"><span class="pre">FromClause</span></tt></a> hierarchy;
1195
it instead is within the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ColumnElement" title="sqlalchemy.sql.expression.ColumnElement"><tt class="xref py py-class docutils literal"><span class="pre">ColumnElement</span></tt></a> family of
1196
expression constructs. We can place this construct the same as any
1197
other column within another <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a>:</p>
1198
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">stmt</span><span class="p">]))</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1199
<div class='show_sql'>SELECT users.name, (SELECT count(addresses.id) AS count_1
1196
1201
WHERE users.id = addresses.user_id) AS anon_1
1198
()</div><span class="go">[(u'jack', 2), (u'wendy', 2), (u'fred', 0), (u'mary', 0)]</span></pre></div>
1203
()</div><span class="go">[(u'jack', 2), (u'wendy', 2)]</span></pre></div>
1200
<p>Alternatively, applying a <tt class="docutils literal"><span class="pre">label()</span></tt> to a select evaluates it as a scalar as
1202
<div class="highlight-pycon+sql"><div class="highlight"><pre><a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">select</span><span class="p">([</span>
1203
<span class="gp">... </span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
1204
<span class="gp">... </span> <span class="n">select</span><span class="p">([</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)],</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span><span class="n">label</span><span class="p">(</span><span class="s">'address_count'</span><span class="p">)</span>
1205
<span class="gp">... </span> <span class="p">]))</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1206
<div class='popup_sql'>SELECT users.name, (SELECT count(addresses.id) AS count_1
1205
<p>To apply a non-anonymous column name to our scalar select, we create
1206
it using <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.SelectBase.label" title="sqlalchemy.sql.expression.SelectBase.label"><tt class="xref py py-meth docutils literal"><span class="pre">SelectBase.label()</span></tt></a> instead:</p>
1207
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)])</span><span class="o">.</span>\
1208
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span>\
1209
<span class="gp">... </span> <span class="n">label</span><span class="p">(</span><span class="s">"address_count"</span><span class="p">)</span>
1210
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">stmt</span><span class="p">]))</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1211
<div class='show_sql'>SELECT users.name, (SELECT count(addresses.id) AS count_1
1208
1213
WHERE users.id = addresses.user_id) AS address_count
1210
()</div><span class="go">[(u'jack', 2), (u'wendy', 2), (u'fred', 0), (u'mary', 0)]</span></pre></div>
1215
()</div><span class="go">[(u'jack', 2), (u'wendy', 2)]</span></pre></div>
1213
1218
<div class="section" id="correlated-subqueries">
1214
<h3>Correlated Subqueries<a class="headerlink" href="#correlated-subqueries" title="Permalink to this headline">¶</a></h3>
1215
<p>Notice in the examples on “scalar selects”, the FROM clause of each embedded
1219
<span id="id2"></span><h3>Correlated Subqueries<a class="headerlink" href="#correlated-subqueries" title="Permalink to this headline">¶</a></h3>
1220
<p>Notice in the examples on <a class="reference internal" href="#scalar-selects"><em>Scalar Selects</em></a>, the FROM clause of each embedded
1216
1221
select did not contain the <tt class="docutils literal"><span class="pre">users</span></tt> table in its FROM clause. This is because
1217
SQLAlchemy automatically attempts to correlate embedded FROM objects to that
1218
of an enclosing query. To disable this, or to specify explicit FROM clauses to
1219
be correlated, use <tt class="docutils literal"><span class="pre">correlate()</span></tt>:</p>
1220
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">],</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">])</span><span class="o">.</span><span class="n">correlate</span><span class="p">(</span><span class="bp">None</span><span class="p">))</span>
1221
<span class="gp">>>> </span><span class="k">print</span> <span class="n">s</span>
1222
<span class="go">SELECT users.name</span>
1223
<span class="go">FROM users</span>
1224
<span class="go">WHERE users.id = (SELECT users.id</span>
1225
<span class="go">FROM users)</span>
1227
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">],</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span>
1228
<span class="gp">... </span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">],</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span><span class="n">correlate</span><span class="p">(</span><span class="n">addresses</span><span class="p">)</span>
1229
<span class="gp">... </span> <span class="p">)</span>
1230
<span class="gp">>>> </span><span class="k">print</span> <span class="n">s</span>
1231
<span class="go">SELECT users.name, addresses.email_address</span>
1232
<span class="go">FROM users, addresses</span>
1233
<span class="go">WHERE users.id = (SELECT users.id</span>
1234
<span class="go">FROM users</span>
1235
<span class="go">WHERE users.id = addresses.user_id)</span></pre></div>
1222
SQLAlchemy automatically <a class="reference internal" href="../glossary.html#term-correlates"><em class="xref std std-term">correlates</em></a> embedded FROM objects to that
1223
of an enclosing query, if present, and if the inner SELECT statement would
1224
still have at least one FROM clause of its own. For example:</p>
1225
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">])</span><span class="o">.</span>\
1226
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span> <span class="o">==</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span>\
1227
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span> <span class="o">==</span> <span class="s">'jack@yahoo.com'</span><span class="p">)</span>
1228
<span class="gp">>>> </span><span class="n">enclosing_stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">])</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">stmt</span><span class="p">)</span>
1229
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">enclosing_stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1230
<div class='show_sql'>SELECT users.name
1232
WHERE users.id = (SELECT addresses.user_id
1234
WHERE addresses.user_id = users.id
1235
AND addresses.email_address = ?)
1236
('jack@yahoo.com',)</div><span class="go">[(u'jack',)]</span></pre></div>
1238
<p>Auto-correlation will usually do what’s expected, however it can also be controlled.
1239
For example, if we wanted a statement to correlate only to the <tt class="docutils literal"><span class="pre">addresses</span></tt> table
1240
but not the <tt class="docutils literal"><span class="pre">users</span></tt> table, even if both were present in the enclosing SELECT,
1241
we use the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.correlate" title="sqlalchemy.sql.expression.Select.correlate"><tt class="xref py py-meth docutils literal"><span class="pre">correlate()</span></tt></a> method to specify those FROM clauses that
1242
may be correlated:</p>
1243
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">])</span><span class="o">.</span>\
1244
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span>\
1245
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'jack'</span><span class="p">)</span><span class="o">.</span>\
1246
<span class="gp">... </span> <span class="n">correlate</span><span class="p">(</span><span class="n">addresses</span><span class="p">)</span>
1247
<span class="gp">>>> </span><span class="n">enclosing_stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">(</span>
1248
<span class="gp">... </span> <span class="p">[</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">])</span><span class="o">.</span>\
1249
<span class="gp">... </span> <span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span>\
1250
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">stmt</span><span class="p">)</span>
1251
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">enclosing_stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1252
<div class='show_sql'>SELECT users.name, addresses.email_address
1253
FROM users JOIN addresses ON users.id = addresses.user_id
1254
WHERE users.id = (SELECT users.id
1256
WHERE users.id = addresses.user_id AND users.name = ?)
1258
</div><span class="go">[(u'jack', u'jack@yahoo.com'), (u'jack', u'jack@msn.com')]</span></pre></div>
1260
<p>To entirely disable a statement from correlating, we can pass <tt class="docutils literal"><span class="pre">None</span></tt>
1261
as the argument:</p>
1262
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">])</span><span class="o">.</span>\
1263
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'wendy'</span><span class="p">)</span><span class="o">.</span>\
1264
<span class="gp">... </span> <span class="n">correlate</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
1265
<span class="gp">>>> </span><span class="n">enclosing_stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">])</span><span class="o">.</span>\
1266
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">stmt</span><span class="p">)</span>
1267
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">enclosing_stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1268
<div class='show_sql'>SELECT users.name
1270
WHERE users.id = (SELECT users.id
1272
WHERE users.name = ?)
1273
('wendy',)</div><span class="go">[(u'wendy',)]</span></pre></div>
1275
<p>We can also control correlation via exclusion, using the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.correlate_except" title="sqlalchemy.sql.expression.Select.correlate_except"><tt class="xref py py-meth docutils literal"><span class="pre">Select.correlate_except()</span></tt></a>
1276
method. Such as, we can write our SELECT for the <tt class="docutils literal"><span class="pre">users</span></tt> table
1277
by telling it to correlate all FROM clauses except for <tt class="docutils literal"><span class="pre">users</span></tt>:</p>
1278
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">])</span><span class="o">.</span>\
1279
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span>\
1280
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'jack'</span><span class="p">)</span><span class="o">.</span>\
1281
<span class="gp">... </span> <span class="n">correlate_except</span><span class="p">(</span><span class="n">users</span><span class="p">)</span>
1282
<span class="gp">>>> </span><span class="n">enclosing_stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">(</span>
1283
<span class="gp">... </span> <span class="p">[</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">])</span><span class="o">.</span>\
1284
<span class="gp">... </span> <span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span>\
1285
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">stmt</span><span class="p">)</span>
1286
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">enclosing_stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1287
<div class='show_sql'>SELECT users.name, addresses.email_address
1288
FROM users JOIN addresses ON users.id = addresses.user_id
1289
WHERE users.id = (SELECT users.id
1291
WHERE users.id = addresses.user_id AND users.name = ?)
1293
</div><span class="go">[(u'jack', u'jack@yahoo.com'), (u'jack', u'jack@msn.com')]</span></pre></div>
1238
1296
<div class="section" id="ordering-grouping-limiting-offset-ing">
1239
1297
<h3>Ordering, Grouping, Limiting, Offset...ing...<a class="headerlink" href="#ordering-grouping-limiting-offset-ing" title="Permalink to this headline">¶</a></h3>
1240
<p>The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.select" title="sqlalchemy.sql.expression.select"><tt class="xref py py-func docutils literal"><span class="pre">select()</span></tt></a> function can take keyword arguments <tt class="docutils literal"><span class="pre">order_by</span></tt>,
1241
<tt class="docutils literal"><span class="pre">group_by</span></tt> (as well as <tt class="docutils literal"><span class="pre">having</span></tt>), <tt class="docutils literal"><span class="pre">limit</span></tt>, and <tt class="docutils literal"><span class="pre">offset</span></tt>. There’s also
1242
<tt class="docutils literal"><span class="pre">distinct=True</span></tt>. These are all also available as generative functions.
1243
<tt class="docutils literal"><span class="pre">order_by()</span></tt> expressions can use the modifiers <tt class="docutils literal"><span class="pre">asc()</span></tt> or <tt class="docutils literal"><span class="pre">desc()</span></tt> to
1244
indicate ascending or descending.</p>
1245
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span> <span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)])</span><span class="o">.</span>\
1246
<span class="gp">... </span> <span class="n">group_by</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">)</span><span class="o">.</span><span class="n">having</span><span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">></span><span class="mi">1</span><span class="p">)</span>
1247
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1248
<div class='popup_sql'>SELECT addresses.user_id, count(addresses.id) AS count_1
1249
FROM addresses GROUP BY addresses.user_id
1250
HAVING count(addresses.id) > ?
1251
(1,)</div><span class="go">[(1, 2), (2, 2)]</span>
1253
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">])</span><span class="o">.</span><span class="n">distinct</span><span class="p">()</span><span class="o">.</span>\
1254
<span class="gp">... </span> <span class="n">order_by</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span><span class="n">desc</span><span class="p">(),</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
1255
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1256
<div class='popup_sql'>SELECT DISTINCT addresses.email_address, addresses.id
1257
FROM addresses ORDER BY addresses.email_address DESC, addresses.id
1258
()</div><span class="go">[(u'www@www.org', 3), (u'wendy@aol.com', 4), (u'jack@yahoo.com', 1), (u'jack@msn.com', 2)]</span>
1260
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="p">])</span><span class="o">.</span><span class="n">offset</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
1261
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="k">print</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1262
<div class='popup_sql'>SELECT addresses.id, addresses.user_id, addresses.email_address
1265
()</div><span class="go">[(2, 1, u'jack@msn.com')]</span></pre></div>
1269
<div class="section" id="inserts-and-updates">
1270
<span id="id1"></span><h2>Inserts and Updates<a class="headerlink" href="#inserts-and-updates" title="Permalink to this headline">¶</a></h2>
1271
<p>Finally, we’re back to INSERT for some more detail. The
1272
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.insert" title="sqlalchemy.sql.expression.insert"><tt class="xref py py-func docutils literal"><span class="pre">insert()</span></tt></a> construct provides a <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ValuesBase.values" title="sqlalchemy.sql.expression.ValuesBase.values"><tt class="xref py py-meth docutils literal"><span class="pre">values()</span></tt></a>
1273
method which can be used to send any value or clause expression to the VALUES
1274
portion of the INSERT:</p>
1275
<div class="highlight-python"><div class="highlight"><pre><span class="c"># insert from a function</span>
1276
<span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">12</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="n">upper</span><span class="p">(</span><span class="s">'jack'</span><span class="p">))</span>
1278
<span class="c"># insert from a concatenation expression</span>
1279
<span class="n">addresses</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="n">email_address</span> <span class="o">=</span> <span class="n">name</span> <span class="o">+</span> <span class="s">'@'</span> <span class="o">+</span> <span class="n">host</span><span class="p">)</span></pre></div>
1281
<p><tt class="docutils literal"><span class="pre">values()</span></tt> can be mixed with per-execution values:</p>
1282
<div class="highlight-python"><div class="highlight"><pre><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
1283
<span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="n">upper</span><span class="p">(</span><span class="s">'jack'</span><span class="p">)),</span>
1284
<span class="n">fullname</span><span class="o">=</span><span class="s">'Jack Jones'</span>
1285
<span class="p">)</span></pre></div>
1287
<p><a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.bindparam" title="sqlalchemy.sql.expression.bindparam"><tt class="xref py py-func docutils literal"><span class="pre">bindparam()</span></tt></a> constructs can be passed, however
1288
the names of the table’s columns are reserved for the “automatic” generation
1290
<div class="highlight-python"><div class="highlight"><pre><span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'_id'</span><span class="p">),</span> <span class="n">name</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'_name'</span><span class="p">))</span>
1292
<span class="c"># insert many rows at once:</span>
1293
<span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
1294
<span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'_id'</span><span class="p">),</span> <span class="n">name</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'_name'</span><span class="p">)),</span>
1295
<span class="p">[</span>
1296
<span class="p">{</span><span class="s">'_id'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name1'</span><span class="p">},</span>
1297
<span class="p">{</span><span class="s">'_id'</span><span class="p">:</span><span class="mi">2</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name2'</span><span class="p">},</span>
1298
<span class="p">{</span><span class="s">'_id'</span><span class="p">:</span><span class="mi">3</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name3'</span><span class="p">},</span>
1299
<span class="p">]</span>
1300
<span class="p">)</span></pre></div>
1302
<p>An UPDATE statement is emitted using the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.update" title="sqlalchemy.sql.expression.update"><tt class="xref py py-func docutils literal"><span class="pre">update()</span></tt></a> construct. These
1303
work much like an INSERT, except there is an additional WHERE clause
1298
<p>Ordering is done by passing column expressions to the
1299
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.SelectBase.order_by" title="sqlalchemy.sql.expression.SelectBase.order_by"><tt class="xref py py-meth docutils literal"><span class="pre">order_by()</span></tt></a> method:</p>
1300
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">])</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
1301
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1302
<div class='show_sql'>SELECT users.name
1303
FROM users ORDER BY users.name
1304
()</div><span class="go">[(u'jack',), (u'wendy',)]</span></pre></div>
1306
<p>Ascending or descending can be controlled using the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ColumnElement.asc" title="sqlalchemy.sql.expression.ColumnElement.asc"><tt class="xref py py-meth docutils literal"><span class="pre">asc()</span></tt></a>
1307
and <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ColumnElement.desc" title="sqlalchemy.sql.expression.ColumnElement.desc"><tt class="xref py py-meth docutils literal"><span class="pre">desc()</span></tt></a> modifiers:</p>
1308
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">])</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">desc</span><span class="p">())</span>
1309
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1310
<div class='show_sql'>SELECT users.name
1311
FROM users ORDER BY users.name DESC
1312
()</div><span class="go">[(u'wendy',), (u'jack',)]</span></pre></div>
1314
<p>Grouping refers to the GROUP BY clause, and is usually used in conjunction
1315
with aggregate functions to establish groups of rows to be aggregated.
1316
This is provided via the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.SelectBase.group_by" title="sqlalchemy.sql.expression.SelectBase.group_by"><tt class="xref py py-meth docutils literal"><span class="pre">group_by()</span></tt></a> method:</p>
1317
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)])</span><span class="o">.</span>\
1318
<span class="gp">... </span> <span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span>\
1319
<span class="gp">... </span> <span class="n">group_by</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
1320
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1321
<div class='show_sql'>SELECT users.name, count(addresses.id) AS count_1
1322
FROM users JOIN addresses
1323
ON users.id = addresses.user_id
1325
()</div><span class="go">[(u'jack', 2), (u'wendy', 2)]</span></pre></div>
1327
<p>HAVING can be used to filter results on an aggregate value, after GROUP BY has
1328
been applied. It’s available here via the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.having" title="sqlalchemy.sql.expression.Select.having"><tt class="xref py py-meth docutils literal"><span class="pre">having()</span></tt></a>
1330
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)])</span><span class="o">.</span>\
1331
<span class="gp">... </span> <span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span>\
1332
<span class="gp">... </span> <span class="n">group_by</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span>\
1333
<span class="gp">... </span> <span class="n">having</span><span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="n">length</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="o">></span> <span class="mi">4</span><span class="p">)</span>
1334
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1335
<div class='show_sql'>SELECT users.name, count(addresses.id) AS count_1
1336
FROM users JOIN addresses
1337
ON users.id = addresses.user_id
1339
HAVING length(users.name) > ?
1340
(4,)</div><span class="go">[(u'wendy', 2)]</span></pre></div>
1342
<p>A common system of dealing with duplicates in composed SELECT statments
1343
is the DISTINCT modifier. A simple DISTINCT clause can be added using the
1344
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.distinct" title="sqlalchemy.sql.expression.Select.distinct"><tt class="xref py py-meth docutils literal"><span class="pre">Select.distinct()</span></tt></a> method:</p>
1345
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">])</span><span class="o">.</span>\
1346
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="o">.</span>
1347
<span class="gp">... </span> <span class="n">contains</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">))</span><span class="o">.</span>\
1348
<span class="gp">... </span> <span class="n">distinct</span><span class="p">()</span>
1349
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1350
<div class='show_sql'>SELECT DISTINCT users.name
1351
FROM users, addresses
1352
WHERE addresses.email_address LIKE '%%' || users.name || '%%'
1353
()</div><span class="go">[(u'jack',), (u'wendy',)]</span></pre></div>
1355
<p>Most database backends support a system of limiting how many rows
1356
are returned, and the majority also feature a means of starting to return
1357
rows after a given “offset”. While common backends like Postgresql,
1358
MySQL and SQLite support LIMIT and OFFSET keywords, other backends
1359
need to refer to more esoteric features such as “window functions”
1360
and row ids to achieve the same effect. The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.limit" title="sqlalchemy.sql.expression.Select.limit"><tt class="xref py py-meth docutils literal"><span class="pre">limit()</span></tt></a>
1361
and <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.Select.offset" title="sqlalchemy.sql.expression.Select.offset"><tt class="xref py py-meth docutils literal"><span class="pre">offset()</span></tt></a> methods provide an easy abstraction
1362
into the current backend’s methodology:</p>
1363
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">])</span><span class="o">.</span>\
1364
<span class="gp">... </span> <span class="n">select_from</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">addresses</span><span class="p">))</span><span class="o">.</span>\
1365
<span class="gp">... </span> <span class="n">limit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">offset</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
1366
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
1367
<div class='show_sql'>SELECT users.name, addresses.email_address
1368
FROM users JOIN addresses ON users.id = addresses.user_id
1370
(1, 1)</div><span class="go">[(u'jack', u'jack@msn.com')]</span></pre></div>
1374
<div class="section" id="inserts-updates-and-deletes">
1375
<span id="inserts-and-updates"></span><h2>Inserts, Updates and Deletes<a class="headerlink" href="#inserts-updates-and-deletes" title="Permalink to this headline">¶</a></h2>
1376
<p>We’ve seen <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.insert" title="sqlalchemy.sql.expression.TableClause.insert"><tt class="xref py py-meth docutils literal"><span class="pre">insert()</span></tt></a> demonstrated
1377
earlier in this tutorial. Where <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.insert" title="sqlalchemy.sql.expression.TableClause.insert"><tt class="xref py py-meth docutils literal"><span class="pre">insert()</span></tt></a>
1378
prodces INSERT, the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.update" title="sqlalchemy.sql.expression.TableClause.update"><tt class="xref py py-meth docutils literal"><span class="pre">update()</span></tt></a>
1379
method produces UPDATE. Both of these constructs feature
1380
a method called <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ValuesBase.values" title="sqlalchemy.sql.expression.ValuesBase.values"><tt class="xref py py-meth docutils literal"><span class="pre">values()</span></tt></a> which specifies
1381
the VALUES or SET clause of the statement.</p>
1382
<p>The <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.ValuesBase.values" title="sqlalchemy.sql.expression.ValuesBase.values"><tt class="xref py py-meth docutils literal"><span class="pre">values()</span></tt></a> method accommodates any column expression
1384
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>\
1385
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">fullname</span><span class="o">=</span><span class="s">"Fullname: "</span> <span class="o">+</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
1386
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span>
1387
<div class='show_sql'>UPDATE users SET fullname=(? || users.name)
1389
COMMIT</div><span class="go"><sqlalchemy.engine.result.ResultProxy object at 0x...></span></pre></div>
1391
<p>When using <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.insert" title="sqlalchemy.sql.expression.TableClause.insert"><tt class="xref py py-meth docutils literal"><span class="pre">insert()</span></tt></a> or <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.update" title="sqlalchemy.sql.expression.TableClause.update"><tt class="xref py py-meth docutils literal"><span class="pre">update()</span></tt></a>
1392
in an “execute many” context, we may also want to specify named
1393
bound parameters which we can refer to in the argument list.
1394
The two constructs will automatically generate bound placeholders
1395
for any column names passed in the dictionaries sent to
1396
<a class="reference internal" href="connections.html#sqlalchemy.engine.Connection.execute" title="sqlalchemy.engine.Connection.execute"><tt class="xref py py-meth docutils literal"><span class="pre">execute()</span></tt></a> at execution time. However, if we
1397
wish to use explicitly targeted named parameters with composed expressions,
1398
we need to use the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.bindparam" title="sqlalchemy.sql.expression.bindparam"><tt class="xref py py-func docutils literal"><span class="pre">bindparam()</span></tt></a> construct.
1399
When using <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.bindparam" title="sqlalchemy.sql.expression.bindparam"><tt class="xref py py-func docutils literal"><span class="pre">bindparam()</span></tt></a> with
1400
<a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.insert" title="sqlalchemy.sql.expression.TableClause.insert"><tt class="xref py py-meth docutils literal"><span class="pre">insert()</span></tt></a> or <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.update" title="sqlalchemy.sql.expression.TableClause.update"><tt class="xref py py-meth docutils literal"><span class="pre">update()</span></tt></a>,
1401
the names of the table’s columns themselves are reserved for the
1402
“automatic” generation of bind names. We can combine the usage
1403
of implicitly available bind names and explicitly named parameters
1404
as in the example below:</p>
1405
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span><span class="o">.</span>\
1406
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'_name'</span><span class="p">)</span> <span class="o">+</span> <span class="s">" .. name"</span><span class="p">)</span>
1407
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">,</span> <span class="p">[</span>
1408
<span class="gp">... </span> <span class="p">{</span><span class="s">'id'</span><span class="p">:</span><span class="mi">4</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name1'</span><span class="p">},</span>
1409
<span class="gp">... </span> <span class="p">{</span><span class="s">'id'</span><span class="p">:</span><span class="mi">5</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name2'</span><span class="p">},</span>
1410
<span class="gp">... </span> <span class="p">{</span><span class="s">'id'</span><span class="p">:</span><span class="mi">6</span><span class="p">,</span> <span class="s">'_name'</span><span class="p">:</span><span class="s">'name3'</span><span class="p">},</span>
1411
<span class="gp">... </span> <span class="p">])</span>
1412
<div class='show_sql'>INSERT INTO users (id, name) VALUES (?, (? || ?))
1413
((4, 'name1', ' .. name'), (5, 'name2', ' .. name'), (6, 'name3', ' .. name'))
1415
<sqlalchemy.engine.result.ResultProxy object at 0x...></div></pre></div>
1417
<p>An UPDATE statement is emitted using the <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.update" title="sqlalchemy.sql.expression.TableClause.update"><tt class="xref py py-meth docutils literal"><span class="pre">update()</span></tt></a> construct. This
1418
works much like an INSERT, except there is an additional WHERE clause
1304
1419
that can be specified:</p>
1305
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="c"># change 'jack' to 'ed'</span>
1306
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>
1307
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">==</span><span class="s">'jack'</span><span class="p">)</span><span class="o">.</span>
1308
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">'ed'</span><span class="p">)</span>
1309
<span class="gp">... </span> <span class="p">)</span>
1310
<div class='popup_sql'>UPDATE users SET name=? WHERE users.name = ?
1420
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>\
1421
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'jack'</span><span class="p">)</span><span class="o">.</span>\
1422
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">'ed'</span><span class="p">)</span>
1424
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">)</span>
1425
<div class='show_sql'>UPDATE users SET name=? WHERE users.name = ?
1312
COMMIT</div><span class="go"><sqlalchemy.engine.base.ResultProxy object at 0x...></span>
1314
<span class="gp">>>> </span><span class="c"># use bind parameters</span>
1315
<span class="gp">>>> </span><span class="n">u</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>\
1316
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="o">==</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'oldname'</span><span class="p">))</span><span class="o">.</span>\
1427
COMMIT</div><span class="go"><sqlalchemy.engine.result.ResultProxy object at 0x...></span></pre></div>
1429
<p>When using <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.TableClause.update" title="sqlalchemy.sql.expression.TableClause.update"><tt class="xref py py-meth docutils literal"><span class="pre">update()</span></tt></a> in an “execute many” context,
1430
we may wish to also use explicitly named bound parameters in the
1431
WHERE clause. Again, <a class="reference internal" href="expression_api.html#sqlalchemy.sql.expression.bindparam" title="sqlalchemy.sql.expression.bindparam"><tt class="xref py py-func docutils literal"><span class="pre">bindparam()</span></tt></a> is the construct
1432
used to achieve this:</p>
1433
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>\
1434
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">bindparam</span><span class="p">(</span><span class="s">'oldname'</span><span class="p">))</span><span class="o">.</span>\
1317
1435
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">bindparam</span><span class="p">(</span><span class="s">'newname'</span><span class="p">))</span>
1318
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">oldname</span><span class="o">=</span><span class="s">'jack'</span><span class="p">,</span> <span class="n">newname</span><span class="o">=</span><span class="s">'ed'</span><span class="p">)</span>
1319
<div class='popup_sql'>UPDATE users SET name=? WHERE users.name = ?
1321
COMMIT</div><span class="go"><sqlalchemy.engine.base.ResultProxy object at 0x...></span>
1323
<span class="gp">>>> </span><span class="c"># with binds, you can also update many rows at once</span>
1324
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">u</span><span class="p">,</span>
1436
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stmt</span><span class="p">,</span> <span class="p">[</span>
1325
1437
<span class="gp">... </span> <span class="p">{</span><span class="s">'oldname'</span><span class="p">:</span><span class="s">'jack'</span><span class="p">,</span> <span class="s">'newname'</span><span class="p">:</span><span class="s">'ed'</span><span class="p">},</span>
1326
1438
<span class="gp">... </span> <span class="p">{</span><span class="s">'oldname'</span><span class="p">:</span><span class="s">'wendy'</span><span class="p">,</span> <span class="s">'newname'</span><span class="p">:</span><span class="s">'mary'</span><span class="p">},</span>
1327
1439
<span class="gp">... </span> <span class="p">{</span><span class="s">'oldname'</span><span class="p">:</span><span class="s">'jim'</span><span class="p">,</span> <span class="s">'newname'</span><span class="p">:</span><span class="s">'jake'</span><span class="p">},</span>
1328
<span class="gp">... </span> <span class="p">)</span>
1329
<div class='popup_sql'>UPDATE users SET name=? WHERE users.name = ?
1330
[('ed', 'jack'), ('mary', 'wendy'), ('jake', 'jim')]
1331
COMMIT</div><span class="go"><sqlalchemy.engine.base.ResultProxy object at 0x...></span>
1333
<span class="gp">>>> </span><span class="c"># update a column to an expression.:</span>
1334
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span>
1335
<span class="gp">... </span> <span class="n">values</span><span class="p">(</span><span class="n">fullname</span><span class="o">=</span><span class="s">"Fullname: "</span> <span class="o">+</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
1336
<span class="gp">... </span> <span class="p">)</span>
1337
<div class='popup_sql'>UPDATE users SET fullname=(? || users.name)
1339
COMMIT</div><span class="go"><sqlalchemy.engine.base.ResultProxy object at 0x...></span></pre></div>
1440
<span class="gp">... </span> <span class="p">])</span>
1441
<div class='show_sql'>UPDATE users SET name=? WHERE users.name = ?
1442
(('ed', 'jack'), ('mary', 'wendy'), ('jake', 'jim'))
1443
COMMIT</div><span class="go"><sqlalchemy.engine.result.ResultProxy object at 0x...></span></pre></div>
1341
1445
<div class="section" id="correlated-updates">
1342
1446
<h3>Correlated Updates<a class="headerlink" href="#correlated-updates" title="Permalink to this headline">¶</a></h3>
1343
1447
<p>A correlated update lets you update a table using selection from another
1344
1448
table, or the same table:</p>
1345
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">],</span> <span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="o">==</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">limit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
1346
<a href='#' class='sql_link'>sql</a><span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="n">fullname</span><span class="o">=</span><span class="n">s</span><span class="p">))</span>
1347
<div class='popup_sql'>UPDATE users SET fullname=(SELECT addresses.email_address
1349
WHERE addresses.user_id = users.id
1352
COMMIT</div><span class="go"><sqlalchemy.engine.base.ResultProxy object at 0x...></span></pre></div>
1449
<div class="highlight-pycon+sql"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">stmt</span> <span class="o">=</span> <span class="n">select</span><span class="p">([</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">email_address</span><span class="p">])</span><span class="o">.</span>\
1450
<span class="gp">... </span> <span class="n">where</span><span class="p">(</span><span class="n">addresses</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span> <span class="o">==</span> <span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span>\
1451
<span class="gp">... </span> <span class="n">limit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
1452
<span class="gp">>>> </span><span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">update</span><span class="p">()</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="n">fullname</span><span class="o">=</span><span class="n">stmt</span><span class="p">))</span>
1453
<div class='show_sql'>UPDATE users SET fullname=(SELECT addresses.email_address
1455
WHERE addresses.user_id = users.id
1458
COMMIT</div><span class="go"><sqlalchemy.engine.result.ResultProxy object at 0x...></span></pre></div>
1355
1461
<div class="section" id="multiple-table-updates">