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)
| 2545 | |
| 2546 | @_generative |
| 2547 | def add_cte(self, *ctes: CTE, nest_here: bool = False) -> Self: |
| 2548 | r"""Add one or more :class:`_sql.CTE` constructs to this statement. |
| 2549 | |
| 2550 | This method will associate the given :class:`_sql.CTE` constructs with |
| 2551 | the parent statement such that they will each be unconditionally |
| 2552 | rendered in the WITH clause of the final statement, even if not |
| 2553 | referenced elsewhere within the statement or any sub-selects. |
| 2554 | |
| 2555 | The optional :paramref:`.HasCTE.add_cte.nest_here` parameter when set |
| 2556 | to True will have the effect that each given :class:`_sql.CTE` will |
| 2557 | render in a WITH clause rendered directly along with this statement, |
| 2558 | rather than being moved to the top of the ultimate rendered statement, |
| 2559 | even if this statement is rendered as a subquery within a larger |
| 2560 | statement. |
| 2561 | |
| 2562 | This method has two general uses. One is to embed CTE statements that |
| 2563 | serve some purpose without being referenced explicitly, such as the use |
| 2564 | case of embedding a DML statement such as an INSERT or UPDATE as a CTE |
| 2565 | inline with a primary statement that may draw from its results |
| 2566 | indirectly. The other is to provide control over the exact placement |
| 2567 | of a particular series of CTE constructs that should remain rendered |
| 2568 | directly in terms of a particular statement that may be nested in a |
| 2569 | larger statement. |
| 2570 | |
| 2571 | E.g.:: |
| 2572 | |
| 2573 | from sqlalchemy import table, column, select |
| 2574 | |
| 2575 | t = table("t", column("c1"), column("c2")) |
| 2576 | |
| 2577 | ins = t.insert().values({"c1": "x", "c2": "y"}).cte() |
| 2578 | |
| 2579 | stmt = select(t).add_cte(ins) |
| 2580 | |
| 2581 | Would render: |
| 2582 | |
| 2583 | .. sourcecode:: sql |
| 2584 | |
| 2585 | WITH anon_1 AS ( |
| 2586 | INSERT INTO t (c1, c2) VALUES (:param_1, :param_2) |
| 2587 | ) |
| 2588 | SELECT t.c1, t.c2 |
| 2589 | FROM t |
| 2590 | |
| 2591 | Above, the "anon_1" CTE is not referenced in the SELECT |
| 2592 | statement, however still accomplishes the task of running an INSERT |
| 2593 | statement. |
| 2594 | |
| 2595 | Similarly in a DML-related context, using the PostgreSQL |
| 2596 | :class:`_postgresql.Insert` construct to generate an "upsert":: |
| 2597 | |
| 2598 | from sqlalchemy import table, column |
| 2599 | from sqlalchemy.dialects.postgresql import insert |
| 2600 | |
| 2601 | t = table("t", column("c1"), column("c2")) |
| 2602 | |
| 2603 | delete_statement_cte = t.delete().where(t.c.c1 < 1).cte("deletions") |
| 2604 |