72

I would like to set a column default value that is based on another table in my SQLAlchemy model.

Currently I have this:

Column('version', Integer, default=1)

What I need is (roughly) this:

Column('version', Integer, default="SELECT MAX(1, MAX(old_versions)) FROM version_table")

How can I implement this in SQLAlchemy?

3 Answers 3

65

The documentation gives the following possibilities for default:

A scalar, Python callable, or ClauseElement representing the default value for this column, which will be invoked upon insert if this column is otherwise not specified in the VALUES clause of the insert.

You may look into using a simple function, or you may just be able to use a select() object.

In your case, maybe something along the lines of:

from sqlalchemy.sql import select, func
...
Column('version', Integer, default=select([func.max(1,
    func.max(version_table.c.old_versions))]))
Sign up to request clarification or add additional context in comments.

6 Comments

I'm aware of the abilities but for some reason I can't seem to formulate the right query. I'd love some specifics, if you can offer them.
@ChrisR: Updated the answer with an example.
That's really close... but in the case where there is no record in version_table max() returns NULL.
@ChrisR: How about using func.coalesce? Something like func.coalesce(func.max(version_table...), --Default Value Here--)? I haven't tested this code, however.
Note this creates a client-side default instead of RDBMS default in the database. See my answer.
|
21

You want server_default

Column('version', Integer, server_default="SELECT MAX(1, MAX(old_versions)) FROM version_table")

1 Comment

is there a way to modify this to filter on a value being used as part of the insert? for example, select max(...) from table where table.some_field=some_value? some_value is one of the values being inserted. EDIT: sadly it looks like no, postgres doesn't allow this: "The value is any variable-free expression (in particular, cross-references to other columns in the current table are not allowed). Subqueries are not allowed either."
1

If you want to use a DML statement to generate the default value, you can simply use the text method to indicate that you are passing DML. You may also need an extra set of parentheses if the engine wants to write this inside a VALUES clause , e.g.:

from sqlachemy import text
Column('version', Integer, default=text("(SELECT MAX(1, MAX(old_versions)) FROM version_table)"))

I've used this technique to use a sequence to override the server default ID generation, e.g.:

Column('version', Integer, default=text("NEXT VALUE FOR someSequence"))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.