# Modifying and Querying Data

## Insert, Update, Delete

See SQLAlchemy’s ORM tutorial and other SQLAlchemy documentation for more information about modifying data with the ORM.

To insert data, pass the model object to `db.session.add()`:

    user = User()
    db.session.add(user)
    db.session.commit()

To update data, modify attributes on the model objects:

    user.verified = True
    db.session.commit()

To delete data, pass the model object to `db.session.delete()`:

    db.session.delete(user)
    db.session.commit()

After modifying data, you must call `db.session.commit()` to commit the changes to the database. Otherwise, they will be discarded at the end of the request.

## Select

See SQLAlchemy’s Querying Guide and other SQLAlchemy documentation for more information about querying data with the ORM.

Queries are executed through `db.session.execute()`. They can be constructed using `select()`. Executing a select returns a `Result` object that has many methods for working with the returned rows.

    user = db.session.execute(db.select(User).filter_by(username=username)).scalar_one()

    users = db.session.execute(db.select(User).order_by(User.username)).scalars()

## Queries for Views

If you write a Flask view function it’s often useful to return a `404 Not Found` error for missing entries. Flask-SQLAlchemy provides some extra query methods.

- `SQLAlchemy.get_or_404()` will raise a 404 if the row with the given id doesn’t exist, otherwise it will return the instance.

- `SQLAlchemy.first_or_404()` will raise a 404 if the query does not return any results, otherwise it will return the first result.

- `SQLAlchemy.one_or_404()` will raise a 404 if the query does not return exactly one result, otherwise it will return the result.

    @app.route("/user-by-id/<int:id>")
    def user_by_id(id):
        user = db.get_or_404(User, id)
        return render_template("show_user.html", user=user)

    @app.route("/user-by-username/<username>")
    def user_by_username(username):
        user = db.one_or_404(db.select(User).filter_by(username=username))
        return render_template("show_user.html", user=user)

You can add a custom message to the 404 error:

>     user = db.one_or_404(
>         db.select(User).filter_by(username=username),
>         description=f"No user named '{username}'."
>     )

## Legacy Query Interface

You may see uses of `Model.query` or `session.query` to build queries. That query interface is considered legacy in SQLAlchemy. Prefer using the `session.execute(select(...))` instead.

See Legacy Query Interface for documentation.