sqlalchemy/sqlalchemy · error · NotImplementedError

params() is not supported for INSERT/UPDATE/DELETE statement

Error message

params() is not supported for INSERT/UPDATE/DELETE statements. To set the values for an INSERT or UPDATE statement, use stmt.values(**parameters).

What it means

The base DML class (`UpdateBase`) defines `params()` purely to raise `NotImplementedError`; it is overridden only by `ValuesBase` (INSERT/UPDATE) where it actually supplies SET/VALUES. Calling `.params(...)` on a `delete()`, or calling it on an INSERT/UPDATE before the `ValuesBase` machinery is engaged, hits this stub. SQLAlchemy deliberately does not let `params()` set row values for DML — values go through `.values()`.

Source

Thrown at lib/sqlalchemy/sql/dml.py:477

                proxy_key,
                fallback_label_name,
                c,
                repeated,
            ) in (self._generate_columns_plus_names(False))
            if is_column_element(c)
        ]

        columns._populate_separate_keys(prox)

    def params(self, *arg: Any, **kw: Any) -> NoReturn:
        """Set the parameters for the statement.

        This method raises ``NotImplementedError`` on the base class,
        and is overridden by :class:`.ValuesBase` to provide the
        SET/VALUES clause of UPDATE and INSERT.

        """
        raise NotImplementedError(
            "params() is not supported for INSERT/UPDATE/DELETE statements."
            " To set the values for an INSERT or UPDATE statement, use"
            " stmt.values(**parameters)."
        )

    @_generative
    def with_dialect_options(self, **opt: Any) -> Self:
        """Add dialect options to this INSERT/UPDATE/DELETE object.

        e.g.::

            upd = table.update().dialect_options(mysql_limit=10)

        .. versionadded:: 1.4 - this method supersedes the dialect options
           associated with the constructor.


        """

View on GitHub (pinned to d9b44cb731)

Solutions

  1. For INSERT/UPDATE, replace `.params(**params)` with `.values(**params)` (the error message itself recommends this).
  2. For DELETE, remove the `.params()` call entirely; bind values via `where(table.c.id == bindparam('id'))` plus execution-time parameters, or use `bindparam` literals.
  3. If you need runtime-bound literal values inside a DML statement, use `bindparam('name', value=...)` inside `.values()` and pass the actual values at `connection.execute(stmt, params)`.
  4. For a Core SELECT, keep using `.params()` — this error only fires for DML; verify the statement type with `type(stmt)`.

Example fix

# before
stmt = users.update().where(users.c.id == 5).params(name="bob")
# raises: params() is not supported for INSERT/UPDATE/DELETE

# after
stmt = users.update().where(users.c.id == 5).values(name="bob")
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy.sql.dml import Insert, Update

def set_parameters(stmt, parameters):
    """Route to the correct method: .values() for DML, .params() for SELECT."""
    if isinstance(stmt, (Insert, Update)):
        return stmt.values(**parameters)
    # DELETE has no VALUES; pass params for execution-time bind instead
    return stmt.params(**parameters) if hasattr(stmt, "params") else stmt

# usage:
# stmt = users.update().where(users.c.id == 1)
# stmt = set_parameters(stmt, {"name": "wendy"})   # -> stmt.values(...)

Prevention

When it happens

Trigger: Calling `stmt = table.delete().where(...)` then `stmt.params(x=1)`; calling `.params()` on a raw `insert()`/`update()` object that has not been built via `ValuesBase`; using the Core/legacy `.params(bind=value)` style (a `select()` idiom) on a DML statement instead of `.values(...)`.

Common situations: Developers porting `select().params(...)` patterns to INSERT/UPDATE; mixing the old `bindparam`/`params` query style with 2.0-style DML builders; passing a dict of column values via `.params()` because it 'looks like' parameter binding; ORM bulk operations code that assumed `params()` works uniformly.

Related errors


AI-assisted analysis of sqlalchemy/sqlalchemy@d9b44cb731 (2026-08-01). Data as JSON: /data/errors/8ca4fd3f95e516e0.json. Report an issue: GitHub.