r"""Add one or more :class:`_sql.CTE` constructs to this statement. This method will associate the given :class:`_sql.CTE` constructs with the parent statement such that they will each be unconditionally rendered in the WITH clause of the final statement, even if not
(self, *ctes: CTE, nest_here: bool = False)
| 2605 | |
| 2606 | @_generative |
| 2607 | def add_cte(self, *ctes: CTE, nest_here: bool = False) -> Self: |
| 2608 | r"""Add one or more :class:`_sql.CTE` constructs to this statement. |
| 2609 | |
| 2610 | This method will associate the given :class:`_sql.CTE` constructs with |
| 2611 | the parent statement such that they will each be unconditionally |
| 2612 | rendered in the WITH clause of the final statement, even if not |
| 2613 | referenced elsewhere within the statement or any sub-selects. |
| 2614 | |
| 2615 | The optional :paramref:`.HasCTE.add_cte.nest_here` parameter when set |
| 2616 | to True will have the effect that each given :class:`_sql.CTE` will |
| 2617 | render in a WITH clause rendered directly along with this statement, |
| 2618 | rather than being moved to the top of the ultimate rendered statement, |
| 2619 | even if this statement is rendered as a subquery within a larger |
| 2620 | statement. |
| 2621 | |
| 2622 | This method has two general uses. One is to embed CTE statements that |
| 2623 | serve some purpose without being referenced explicitly, such as the use |
| 2624 | case of embedding a DML statement such as an INSERT or UPDATE as a CTE |
| 2625 | inline with a primary statement that may draw from its results |
| 2626 | indirectly. The other is to provide control over the exact placement |
| 2627 | of a particular series of CTE constructs that should remain rendered |
| 2628 | directly in terms of a particular statement that may be nested in a |
| 2629 | larger statement. |
| 2630 | |
| 2631 | E.g.:: |
| 2632 | |
| 2633 | from sqlalchemy import table, column, select |
| 2634 | |
| 2635 | t = table("t", column("c1"), column("c2")) |
| 2636 | |
| 2637 | ins = t.insert().values({"c1": "x", "c2": "y"}).cte() |
| 2638 | |
| 2639 | stmt = select(t).add_cte(ins) |
| 2640 | |
| 2641 | Would render: |
| 2642 | |
| 2643 | .. sourcecode:: sql |
| 2644 | |
| 2645 | WITH anon_1 AS ( |
| 2646 | INSERT INTO t (c1, c2) VALUES (:param_1, :param_2) |
| 2647 | ) |
| 2648 | SELECT t.c1, t.c2 |
| 2649 | FROM t |
| 2650 | |
| 2651 | Above, the "anon_1" CTE is not referenced in the SELECT |
| 2652 | statement, however still accomplishes the task of running an INSERT |
| 2653 | statement. |
| 2654 | |
| 2655 | Similarly in a DML-related context, using the PostgreSQL |
| 2656 | :class:`_postgresql.Insert` construct to generate an "upsert":: |
| 2657 | |
| 2658 | from sqlalchemy import table, column |
| 2659 | from sqlalchemy.dialects.postgresql import insert |
| 2660 | |
| 2661 | t = table("t", column("c1"), column("c2")) |
| 2662 | |
| 2663 | delete_statement_cte = t.delete().where(t.c.c1 < 1).cte("deletions") |
| 2664 |