Column INSERT/UPDATE Defaults

列のINSERTとUPDATEのデフォルトは、行の特定の列に デフォルト値 を作成する関数を参照します。これは、 その列のINSERT文またはUPDATE文に値が指定されていない 場合に、INSERT文またはUPDATE文がその行に対して処理されるときに行われます。つまり、テーブルに”timestamp”という列があり、この列の値を含まないINSERT文が処理される場合、INSERTのデフォルトは”timestamp”列に挿入される値として使用される新しい値(現在の時刻など)を作成します。文にこの列の値が*含まれる*場合、デフォルトは発生*しません*。

カラムのデフォルトは、 DDL のスキーマと共にデータベース内で定義されたサーバ側の関数や定数値、あるいはSQLAlchemyが発行するINSERT文やUPDATE文の中で直接描画されるSQL式です。また、データがデータベースに渡される前にSQLAlchemyが呼び出すクライアント側のPython関数や定数値もあります。

Note

カラムデフォルトハンドラは、呼び出された時に文に提供されるINSERT文とUPDATE文の入力値を途中で取得して変更する構文と混同してはいけません。これは data marshalling として知られており、データベースに送信される前にアプリケーションによって何らかの方法でカラム値が変更されます。SQLAlchemyはこれを実現するいくつかの方法を提供しますが、これには custom datatypes , SQL execution events ,ORM custom validators および attribute events の使用が含まれます。カラムデフォルトは、SQL DML 文のカラムに 値が存在しない 場合にのみ呼び出されます。

SQLAlchemyは、INSERT文とUPDATE文の間に存在しない値に対して行われるデフォルトの生成関数に関する一連の機能を提供します。オプションは次のとおりです。

  • INSERTおよびUPDATE操作時にデフォルトとして使用されるスカラー値*INSERTおよびUPDATE操作時に実行されるPython関数*INSERT文に埋め込まれた(場合によっては事前に実行される)SQL式*UPDATE文に埋め込まれたSQL式*INSERT時に使用されるサーバ側のデフォルト値*UPDATE時に使用されるサーバ側のトリガのマーカー

全ての挿入/更新のデフォルトの一般的なルールは、特定の列の値が execute() パラメータとして渡されない場合にのみ有効になるということです。そうでなければ、与えられた値が使用されます。

Scalar Defaults

最も単純な種類のデフォルトは、列のデフォルト値として使用されるスカラー値です:

Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))

上記では、他の値が指定されない場合、INSERT時に値”12”がカラム値としてバインドされます。

スカラー値をUPDATE文に関連付けることもできますが、これはあまり一般的ではありません(UPDATE文は通常、動的なデフォルトを探します):

Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))

Python-Executed Functions

Column.default および Column.onupdate キーワード引数もPython関数を受け付けます。これらの関数は、その列に他の値が指定されていない場合、挿入または更新時に呼び出され、返された値が列の値として使用されます。以下は、インクリメントするカウンタを主キー列に割り当てるおおまかな”シーケンス”を示しています:

# a function which counts upwards
i = 0

def mydefault():
    global i
    i += 1
    return i

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True, default=mydefault),
)

実際の”シーケンスをインクリメントする”動作には、通常はデータベースの組み込み機能を使用する必要があります。組み込み機能には、シーケンスオブジェクトやその他の自動インクリメント機能が含まれている場合があります。主キー列の場合、SQLAlchemyはほとんどの場合、これらの機能を自動的に使用します。 Column.autoincrement フラグを含む Column のAPIドキュメントと、標準的な主キー生成テクニックの背景については、この章の後半の Sequence のセクションを参照してください。

onupdateを説明するために、Pythonの datetime 関数の nowColumn.onupdate 属性に代入します:

import datetime

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'last_updated' to be populated with datetime.now()
    Column("last_updated", DateTime, onupdate=datetime.datetime.now),
)

update文が実行され、 last_updated に値が渡されない場合、 datetime.datetime.now() Python関数が実行され、その戻り値が last_updated の値として使用されます。 now を呼び出さずに関数自体として提供していることに注意してください(つまり、括弧が付いていません)。SQLAlchemyは、ステートメントが実行されたときに関数を実行します。

Context-Sensitive Default Functions

Column.defaultColumn.onupdate で使用されるPython関数は、値を決定するために現在の文のコンテキストを使用することもあります。文の「コンテキスト」は、実行される文に関するすべての情報を含む内部SQLAlchemyオブジェクトで、ソース式、それに関連付けられたパラメータ、カーソルなどが含まれます。デフォルト生成に関するこのコンテキストの典型的な使用例は、行に挿入または更新される他の値にアクセスすることです。コンテキストにアクセスするには、単一の context 引数を受け付ける関数を提供します:

def mydefault(context):
    return context.get_current_parameters()["counter"] + 12

t = Table(
    "mytable",
    metadata_obj,
    Column("counter", Integer),
    Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)

上記のデフォルトの生成関数が適用され、 counter_plus_twelve の値が指定されていないすべてのINSERT文とUPDATE文が実行されます。この値は、 counter 列の実行時に存在する値に12を加えた値になります。

例えば Connection.execute() に複数のパラメータセットが渡されるなど、”executemany”スタイルで実行される単一の文の場合、ユーザ定義関数はパラメータセットごとに1回呼び出されます。複数の値を持つ Insert 構文のユースケース(例えば Insert.values() メソッドによって複数のVALUESclauseが設定される場合)では、ユーザ定義関数もパラメータセットごとに1回呼び出されます。

関数が呼び出されると、特別なメソッド DefaultExecutionContext.get_current_parameters() がコンテキストオブジェクト( DefaultExecutionContext のサブクラス)から利用可能になります。このメソッドは、INSERT文またはUPDATE文の値の完全なセットを表す値への列キーのディクショナリを返します。複数の値を持つINSERT構文の場合、個々のVALUES句に対応するパラメータのサブセットは、完全なパラメータディクショナリから分離され、単独で返されます。

New in version 1.2:

DefaultExecutionContext.get_current_parameters() メソッドが追加されました。これは、複数のVALUES句を個々のパラメータ辞書に編成するサービスを提供することによって、現在も存在する aultExecutionContext.current_parameters 属性を改良したものです。

Client-Invoked SQL Expressions

Column.default キーワードと Column.onupdate キーワードにもSQL式を渡すことができます。ほとんどの場合、SQL式はINSERT文またはUPDATE文の中でインラインでレンダリングされます:

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'create_date' to default to now()
    Column("create_date", DateTime, default=func.now()),
    # define 'key' to pull its default from the 'keyvalues' table
    Column(
        "key",
        String(20),
        default=select(keyvalues.c.key).where(keyvalues.c.type="type1"),
    ),
    # define 'last_modified' to use the current_timestamp SQL function on update
    Column("last_modified", DateTime, onupdate=func.utc_timestamp()),
)

上記の例では、INSERT文の実行中に、SQL関数の now() (バックエンドによっては、ほとんどの場合、 NOW() または CURRENT_TIMESTAMP にコンパイルされます)の結果が「create_date」列に入力され、別のテーブルからのSELECT副問い合わせの結果が「key」列に入力されます。このテーブルに対してUPDATE文が発行されると、MySQL関数のSQLの UTC_TIMESTAMP() の値が last_modified 列に入力されます。

Note

func 構文でSQL関数を使用する場合、名前付きの関数を「呼び出し」ます。例えば、括弧を使って func.now() のようにします。これは、 datetime.datetime のようにデフォルトで呼び出すことができるPythonを指定する場合とは異なります。この場合、関数自体は渡しますが、自分自身では呼び出しません。SQL関数の場合、 func.now() を呼び出すと、出力されるSQLに”NOW”関数をレンダリングするSQL式オブジェクトが返されます。

Column.defaultColumn.onupdate で指定されたデフォルトと更新のSQL式は、INSERT文やUPDATE文が発生した時にSQLAlchemyによって明示的に呼び出され、以下に挙げる特定の場合を除いて、通常はDML文の中でインラインでレンダリングされます。これは”サーバ側”のデフォルトとは異なります。”サーバ側”のデフォルトはテーブルのDDL定義の一部であり、例えば”CREATE TABLE”文の一部であり、より一般的です。サーバ側のデフォルトについては、次のセクション Server-invoked DDL-Explicit Default Expressions を参照してください。

Column.default で指定されたSQL式を主キー列で使用する場合、SQLAlchemyがデフォルトの生成SQL関数を”事前に実行”する必要がある場合があります。つまり、これは別のSE LE CT文で呼び出され、結果の値がパラメータとしてINSERTに渡されます。これは、この主キー値を返すように要求されているINSERT文の主キー列に対してのみ発生します。この場合、RETURNINGまたは cursor.lastrowid は使用できません。 insert.inline フラグを指定する Insert 構文は、常にデフォルトの式をインラインで表示します。

文が単一のパラメータセットで実行される場合(つまり、”executemany”スタイルの実行ではない場合)、返される CursorResult には、 CursorResult.postfetch_cols() 経由でアクセス可能なコレクションが含まれます。このコレクションには、インラインで実行されるデフォルトを持つすべての Column オブジェクトのリストが含まれます。同様に、文にバインドされたすべてのパラメータ(事前に実行されたすべてのPythonおよびSQL式を含む)は、 CursorResultCursorResult.last_inserted_params() または CursorResult.last_updated_params() コレクションに存在します。 CursorResult.inserted_primary_key コレクションには、挿入された行のプライマリキー値のリスト(単一列と複合列のプライマリキーが同じフォーマットで表されるようなリスト)が含まれます。

Server-invoked DDL-Explicit Default Expressions

SQL式defaultのバリアントは Column.server_default です。これは Table.create() 操作中にCREATE TABLE文に置かれます。

t = Table(
    "test",
    metadata_obj,
    Column("abc", String(20), server_default="abc"),
    Column("created_at", DateTime, server_default=func.sysdate()),
    Column("index_value", Integer, server_default=text("0")),
)

上記のテーブルに対してcreateを呼び出すと、以下が生成されます。

CREATE TABLE test (
    abc varchar(20) default 'abc',
    created_at datetime default sysdate,
    index_value integer default 0
)

上記の例は、 Column.server_default の2つの典型的な使用例、SQL関数の使用例(上記の例ではSYSDATE)、およびサーバ側の定数値(上記の例では整数”0”)を示しています。SQLAlchemyは通常、これらの値に対して引用やエスケープを行わないので、生の値を渡すのではなく、リテラルSQL値に対して text() 構文を使用することをお勧めします。

クライアントが生成する式と同様に、 Column.server_default は一般的にSQL式を調整することができますが、これらは通常、埋め込みSELECTのようなより複雑な場合ではなく、単純な関数と式であることが期待されます。

Marking Implicitly Generated Values, timestamps, and Triggered Columns

他のサーバ側のデータベース機構に基づいてINSERTやUPDATEで新しい値を生成するカラム(例えば、いくつかのプラットフォームのTIMESTAMPカラムで見られるようなデータベース固有の自動生成動作や、INSERTやUPDATEで新しい値を生成するために呼び出すカスタムトリガなど)は、 FetchedValue をマーカとして呼び出すことができます:

from sqlalchemy.schema import FetchedValue

t = Table(
    "test",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("abc", TIMESTAMP, server_default=FetchedValue()),
    Column("def", String(20), server_onupdate=FetchedValue()),
)

FetchedValue インジケータは、CREATE TABLEのレンダリングされたDDLには影響しません。代わりに、INSERT文やUPDATE文の処理中にデータベースによって新しい値が設定されるカラムとしてマークされます。サポートするデータベースでは、カラムが文のRETURNING句やOUTPUT句の一部であることを示すために使用されることがあります。SQLAlchemy ORMなどのツールは、このような操作の後にカラムの値を取得する方法を知るために、このマーカーを利用します。特に、 ValuesBase.return_defaults() メソッドを Insert または Update 構文と一緒に使用して、これらの値が返されることを示すことができます。

ORMで FetchedValue を使う方法の詳細については Fetching Server-Generated Defaults を参照してください。

Warning

Column.server_onupdate ディレクティブ**は現在MySQLの”ON UPDATE CURRENT_TIMESTAMP()”節を 生成しません 。この節を生成する方法の背景については Rendering ON UPDATE CURRENT TIMESTAMP for MySQL / MariaDB’s explicit_defaults_for_timestamp を参照してください。

Defining Sequences

SQLAlchemyは Sequence オブジェクトを使ってデータベースのシーケンスを表現します。これは”列デフォルト”の特殊なケースとみなされます。これは明示的にシーケンスをサポートしているデータベースに対してのみ効果があります。SQLAlchemyにはPostgreSQL、Oracle、MS SQL Server、MariaDBが含まれます。それ以外では Sequence オブジェクトは無視されます。

Tip

最近のデータベースエンジンでは、整数のプライマリキー値の生成には Sequence よりも Identity 構文の方が好まれるようです。この構文の背景については Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY) を参照してください。

Sequence は、INSERT操作中に使用される”デフォルト”のジェネレータとして任意の列に配置することができます。また、必要に応じてUPDATE操作中に起動するように設定することもできます。これは最も一般的には、単一の整数のプライマリキー列と組み合わせて使用されます:

table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        Sequence("cart_id_seq", start=1),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

上記の場合、テーブル cartitemscart_id_seq という名前のシーケンスに関連付けられています。上記のテーブルに対して MetaData.create_all() を発行すると、次のようになります。

CREATE SEQUENCE cart_id_seq START WITH 1

CREATE TABLE cartitems (
  cart_id INTEGER NOT NULL,
  description VARCHAR(40),
  createdate TIMESTAMP WITHOUT TIME ZONE,
  PRIMARY KEY (cart_id)
)

Tip

明示的なスキーマ名(詳細は Specifying the Schema Name を参照)を持つテーブルを使用する場合、 Table の設定されたスキーマは、埋め込まれた Sequence によって自動的に共有 されません 。代わりに、 Sequence.schema を指定してください:

Sequence("cart_id_seq", start=1, schema="some_schema")

cart_id 列に明示的な値が渡されずに、 cartitems テーブルに対して Insert DML構文が呼び出されると、「cart_id_seq」シーケンスを使用して、関連するバックエンドで値が生成されます。通常、シーケンス関数はINSERT文に埋め込まれ、RETURNINGと組み合わされて、新たに生成された値をPythonプロセスに返すことができます。

INSERT INTO cartitems (cart_id, description, createdate)
VALUES (next_val(cart_id_seq), 'some description', '2015-10-15 12:00:15')
RETURNING cart_id

Connection.execute() を使用して Insert 構文を呼び出す場合、 Sequence を使用して生成されたものを含む(ただしこれに限定されない)新たに生成された主キー識別子は、 CursorResult.inserted_primary_key 属性を使用して CursorResult 構文から利用できます。

SequencePython側 のデフォルトジェネレータとして Column に関連付けられている場合、 Sequence も”CREATE SEQUENCE”および”DROPSEQUENCE”DDLの対象になります。これは、一連のテーブルのDDLを生成するために MetaData.create_all() を使用する場合のように、所有する Table に対して同様のDDLが生成される場合です。

Sequence は、 MetaData 構造体に直接関連付けることもできます。これにより、 Sequence を一度に複数の Table で使用することができ、 MetaData.schema パラメータを継承することもできます。背景については Associating a Sequence with the MetaData を参照してください。

Associating a Sequence on a SERIAL column

PostgreSQLのSERIALデータ型は自動インクリメント型であり、CREATE TABLEが発行された時に暗黙的にPostgreSQLシーケンスが作成されることを意味します。 Sequence 構文は、 Column に対して指定された場合、 Sequence.optional パラメータに対して True の値を指定することで、この特定の場合には使用すべきでないことを示すことができます。これにより、与えられた Sequence を、代替の主キー生成システムを持たないバックエンドに対して使用することができますが、特定の列に対してシーケンスを自動的に生成するPostgreSQLのようなバックエンドに対しては無視することができます:

table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        # use an explicit Sequence where available, but not on
        # PostgreSQL where SERIAL will be used
        Sequence("cart_id_seq", start=1, optional=True),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

上の例では、PostgreSQLのための` CREATE TABLE` は、列 cart_id に対してデータ型 SERIAL を使用し、シーケンス cart_id_seq は無視されます。しかしOracleでは、シーケンス cart_id_seq は明示的に作成されます。

Tip

This particular interaction of SERIAL and SEQUENCE is fairly legacy, and as in other cases, using Identity instead will simplify the operation to simply use IDENTITY on all supported backends.

このSERIALとSEQUENCEの特殊な相互作用はかなり古いものであり、他の場合と同様に、代わりに Identity を使用すると、サポートされているすべてのバックエンドで単に IDENTITY を使用するだけで操作が簡単になります。

Executing a Sequence Standalone

SEQUENCEはSQLにおける最初のクラスのスキーマオブジェクトであり、データベース内で独立して値を生成するために使用することができます。 Sequence オブジェクトがあれば、”next value”命令を使ってSQL実行メソッドに直接渡すことで呼び出すことができます:

with my_engine.connect() as conn:
    seq = Sequence("some_sequence", start=1)
    nextid = conn.execute(seq)

Sequence の”next value”関数をSELECTやINSERTのようにSQL文の中に埋め込むには、 Sequence.next_value() メソッドを使用します。このメソッドは、文のコンパイル時に、対象のバックエンドに適したSQL関数を返します。

>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT nextval('some_sequence') AS next_value_1

Associating a Sequence with the MetaData

任意の Table オブジェクトに関連付けられる Sequence の場合、 Sequence.MetaData パラメータを使用して、 Sequence を特定の MetaData に関連付けることができます:

seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)

このようなシーケンスは、通常の方法で列に関連付けることができます:

table = Table(
    "cartitems",
    metadata_obj,
    seq,
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

上の例では、 Sequence オブジェクトは独立したスキーマ構成体として扱われ、単独で存在することも、テーブル間で共有されることもできます。

SequenceMetaData と明示的に関連付けると、以下のような振る舞いが可能になります:

Associating a Sequence as the Server Side Default

Note

以下のテクニックは、PostgreSQLデータベースでのみ動作することが分かっています。Oracleでは動作しません。

これまでの節では、 Python側のデフォルトジェネレータ として、 SequenceColumn に関連付ける方法を説明してきました:

Column(
    "cart_id",
    Integer,
    Sequence("cart_id_seq", metadata=metadata_obj, start=1),
    primary_key=True,
)

上記の場合、関連する Table がCREATE/DROPの対象になると、 Sequence は自動的にCREATE SEQUENCE/DROP SEQUENCE DDLの対象になります。しかし、CREATE TABLEが発行された時に、その列のサーバ側のデフォルトとしてシーケンスは 表示されません

シーケンスをサーバ側のデフォルトとして使用したい場合、つまりSQLコマンドラインからテーブルにINSERTコマンドを発行してもシーケンスが実行されるようにしたい場合は、 Column.server_default パラメータを、 Sequence.next_value() メソッドから利用可能なシーケンスの値生成関数と組み合わせて使用できます。以下では、同じ Column にPython側のデフォルトジェネレータとしてもサーバ側のデフォルトジェネレータとしても関連付けられていることを説明します:

cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        cart_id_seq,
        server_default=cart_id_seq.next_value(),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

ORMでは:

class CartItem(Base):
    __tablename__ = "cartitems"

    cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
    cart_id = Column(
        Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
    )
    description = Column(String(40))
    createdate = Column(DateTime)

“CREATE TABLE”文が発行されると、PostgreSQLでは以下のように発行されます。

CREATE TABLE cartitems (
    cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
    description VARCHAR(40),
    createdate TIMESTAMP WITHOUT TIME ZONE,
    PRIMARY KEY (cart_id)
)

Python側とサーバ側のデフォルト生成コンテキストの両方に Sequence を配置することで、”プライマリキーフェッチ”ロジックがすべての場合に動作することが保証されます。通常、シーケンス対応のデータベースでは、INSERT文のRETURNINGもサポートされています。これは、SQLAlchemyがこの文を発行するときに自動的に使用されます。ただし、RETURNINGが特定の挿入に使用されない場合、SQLAlchemyはINSERT文自体の外部でシーケンスを”事前実行”することを好みます。これは、シーケンスがPython側のデフォルトジェネレータ関数として含まれている場合にのみ機能します。

また、この例では Sequence を囲んでいる MetaData に直接関連付けています。これもまた、 Sequence がデフォルトのスキーマを含む MetaData コレクションのパラメータに完全に関連付けられていることを保証します。

See also

Sequences/SERIAL/IDENTITY - PostgreSQLダイアレクトドキュメント内

RETURNING Support - Oracleダイアレクトドキュメント内

Computed Columns (GENERATED ALWAYS AS)

New in version 1.3.11.

Computed 構文を使用すると、 Column を”GENERATED ALWAYS AS”列、つまりデータベースサーバーによって計算された値を持つ列としてDDLで宣言することができます。この構文は、 CheckConstraint と同様の方法で、通常は文字列または text() 構文を使用してテキストで宣言されたSQL式を受け入れます。その後、SQL式はデータベースサーバーによって解釈され、行内の列の値が決定されます。

例:

from sqlalchemy import Table, Column, MetaData, Integer, Computed

metadata_obj = MetaData()

square = Table(
    "square",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("side", Integer),
    Column("area", Integer, Computed("side * side")),
    Column("perimeter", Integer, Computed("4 * side")),
)

PostgreSQL 12のバックエンドで実行した場合の square テーブルのDDLは以下のようになります。

CREATE TABLE square (
    id SERIAL NOT NULL,
    side INTEGER,
    area INTEGER GENERATED ALWAYS AS (side * side) STORED,
    perimeter INTEGER GENERATED ALWAYS AS (4 * side) STORED,
    PRIMARY KEY (id)
)

値がINSERTとUPDATEで保持されるか、フェッチで計算されるかは、データベースの実装の詳細です。前者は”stored”、後者は”virtual”と呼ばれます。両方をサポートするデータベース実装もありますが、どちらか一方しかサポートしないものもあります。オプションの Computed.persisted フラグは、”STORED”または”VIRTUAL”キーワードをDDLでレンダリングするかどうかを示すために、 True または False として指定できます。ただし、このキーワードがターゲットバックエンドでサポートされていない場合はエラーが発生します。未設定のままにしておくと、ターゲットバックエンドのデフォルトが使用されます。

Computed 構文は FetchedValue オブジェクトのサブクラスで、対象となる Column の”server default”および”serveronupdate”ジェネレータとして自身を設定します。これは、INSERTおよびUPDATE文が生成されるときにデフォルトの生成列として扱われることと、ORMを使用するときに生成列としてフェッチされることを意味します。これには、RETURNINGをサポートするデータベースではデータベースのRETURNING句の一部となり、生成された値がフェッチされることが含まれます。

Note

Computed 構文で定義された Column は、サーバが適用する値以外の値を格納することはできません。INSERTまたはUPDATEで書き込まれる列に値が渡された場合のSQLAlchemyの動作では、現在、その値は無視されます。

“GENERATED ALWAYS AS”は現在以下でサポートされています。

  • MySQLバージョン5.7以降

  • MariaDB 10.xシリーズ以降

  • PostgreSQLバージョン12

  • Oracle - RETURNINGがUPDATEで正しく動作しないことに注意してください。

    (計算結果列を含むUPDATE.RETURNINGが描画されると、この結果に対する警告が表示されます)

  • Microsoft SQL Server

  • SQLiteバージョン3.31

Computed がサポートされていないバックエンドで使用された場合、ターゲットのダイアレクトがそれをサポートしていなければ、構文のレンダリング時に CompileError が発生します。それ以外の場合、ダイアレクトがサポートしていても、使用中の特定のデータベースサーババージョンがサポートしていなければ、DDLがデータベースに発行されたときに DBAPIError のサブクラス(通常は OperationalError )が発生します。

See also

Computed

Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

New in version 1.4.

Identity 構文を使用すると、 Column をidentity列として宣言し、DDLで”GENERATED {ALWAYS BY DEFAULT} AS IDENTITY”としてレンダリングすることができます。identity列の値は、インクリメント(またはデクリメント)シーケンスを使用してデータベースサーバーによって自動的に生成されます。この構文は、 Sequence を使用してデータベースの動作を制御するオプションのほとんどを共有しています。

例:

from sqlalchemy import Table, Column, MetaData, Integer, Identity, String

metadata_obj = MetaData()

data = Table(
    "data",
    metadata_obj,
    Column("id", Integer, Identity(start=42, cycle=True), primary_key=True),
    Column("data", String),
)

PostgreSQL 12のバックエンドで実行した場合の data テーブルのDDLは以下のようになります:

CREATE TABLE data (
    id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
    data VARCHAR,
    PRIMARY KEY (id)
)

文にまだ id 列の値が含まれていない場合、データベースは挿入時に 42 から始まる id 列の値を生成します。identity列は、バックエンドに応じて、文で渡された値を無視したり、エラーを発生させたりして、データベースが列の値を生成することを要求することもできます。このモードを有効にするには、 Identity 構文でパラメータ Identity.alwaysTrue に設定します。前の例を更新してこのパラメータを含めると、次のDDLが生成されます。

CREATE TABLE data (
    id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
    data VARCHAR,
    PRIMARY KEY (id)
)

Identity 構文は FetchedValue オブジェクトのサブクラスで、対象となる Column の”server default”ジェネレータとして設定されます。これは、INSERT文が生成されるときにデフォルトの生成列として扱われることと、ORMを使用するときに生成列としてフェッチされることを意味します。これには、RETURNINGをサポートするデータベースの場合、データベースのRETURNING句の一部となり、生成された値がフェッチされることが含まれます。

Identity 構文は現在以下のものでサポートされています:

  • PostgreSQLバージョン10

  • Oracleバージョン12。また、デフォルトの生成モードを有効にするために always=None を渡し、”ON NULL”を指定するために”BY DEFAULT”ID列とともに on_null=True パラメータを渡すこともサポートしています。

  • Microsoft SQL Server。MSSQLは、 startincrement パラメータのみをサポートし、他のパラメータをすべて無視するカスタム構文を使用します。

サポートされていないバックエンドで Identity が使用された場合、これは無視され、カラムを自動的にインクリメントするデフォルトのSQLAlchemyロジックが使用されます。

ColumnIdentity を指定し、かつ Column.autoincrementFalse に設定した場合、エラーが発生します。

See also

Identity

Default Objects API

Object Name Description

ColumnDefault

A plain default value on a column.

Computed

Defines a generated column, i.e. “GENERATED ALWAYS AS” syntax.

DefaultClause

A DDL-specified DEFAULT column value.

DefaultGenerator

Base class for column default values.

FetchedValue

A marker for a transparent database-side default.

Identity

Defines an identity column, i.e. “GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY” syntax.

Sequence

Represents a named database sequence.

class sqlalchemy.schema.Computed

Defines a generated column, i.e. “GENERATED ALWAYS AS” syntax.

The Computed construct is an inline construct added to the argument list of a Column object:

from sqlalchemy import Computed

Table('square', metadata_obj,
    Column('side', Float, nullable=False),
    Column('area', Float, Computed('side * side'))
)

See the linked documentation below for complete details.

New in version 1.3.11.

Members

__init__(), copy()

method sqlalchemy.schema.Computed.__init__(sqltext: _DDLColumnArgument, persisted: bool | None = None) None

Construct a GENERATED ALWAYS AS DDL construct to accompany a Column.

Parameters:
  • sqltext

    A string containing the column generation expression, which will be used verbatim, or a SQL expression construct, such as a text() object. If given as a string, the object is converted to a text() object.

    Warning

    The Computed.sqltext argument to Computed can be passed as a Python string argument, which will be treated as trusted SQL text and rendered as given. DO NOT PASS UNTRUSTED INPUT TO THIS PARAMETER.

  • persisted

    Optional, controls how this column should be persisted by the database. Possible values are:

    • None, the default, it will use the default persistence defined by the database.

    • True, will render GENERATED ALWAYS AS ... STORED, or the equivalent for the target database if supported.

    • False, will render GENERATED ALWAYS AS ... VIRTUAL, or the equivalent for the target database if supported.

    Specifying True or False may raise an error when the DDL is emitted to the target database if the database does not support that persistence option. Leaving this parameter at its default of None is guaranteed to succeed for all databases that support GENERATED ALWAYS AS.

method sqlalchemy.schema.Computed.copy(*, target_table: Table | None = None, **kw: Any) Computed

Deprecated since version 1.4: The Computed.copy() method is deprecated and will be removed in a future release.

class sqlalchemy.schema.ColumnDefault

A plain default value on a column.

This could correspond to a constant, a callable function, or a SQL clause.

ColumnDefault is generated automatically whenever the default, onupdate arguments of Column are used. A ColumnDefault can be passed positionally as well.

For example, the following:

Column('foo', Integer, default=50)

Is equivalent to:

Column('foo', Integer, ColumnDefault(50))
class sqlalchemy.schema.DefaultClause

A DDL-specified DEFAULT column value.

DefaultClause is a FetchedValue that also generates a “DEFAULT” clause when “CREATE TABLE” is emitted.

DefaultClause is generated automatically whenever the server_default, server_onupdate arguments of Column are used. A DefaultClause can be passed positionally as well.

For example, the following:

Column('foo', Integer, server_default="50")

Is equivalent to:

Column('foo', Integer, DefaultClause("50"))
class sqlalchemy.schema.DefaultGenerator

Base class for column default values.

This object is only present on column.default or column.onupdate. It’s not valid as a server default.

class sqlalchemy.schema.FetchedValue

A marker for a transparent database-side default.

Use FetchedValue when the database is configured to provide some automatic default for a column.

E.g.:

Column('foo', Integer, FetchedValue())

Would indicate that some trigger or default generator will create a new value for the foo column during an INSERT.

Class signature

class sqlalchemy.schema.FetchedValue (sqlalchemy.sql.expression.SchemaEventTarget)

class sqlalchemy.schema.Sequence

Represents a named database sequence.

The Sequence object represents the name and configurational parameters of a database sequence. It also represents a construct that can be “executed” by a SQLAlchemy Engine or Connection, rendering the appropriate “next value” function for the target database and returning a result.

The Sequence is typically associated with a primary key column:

some_table = Table(
    'some_table', metadata,
    Column('id', Integer, Sequence('some_table_seq', start=1),
    primary_key=True)
)

When CREATE TABLE is emitted for the above Table, if the target platform supports sequences, a CREATE SEQUENCE statement will be emitted as well. For platforms that don’t support sequences, the Sequence construct is ignored.

Class signature

class sqlalchemy.schema.Sequence (sqlalchemy.schema.HasSchemaAttr, sqlalchemy.schema.IdentityOptions, sqlalchemy.schema.DefaultGenerator)

method sqlalchemy.schema.Sequence.__init__(name: str, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, schema: str | Literal[SchemaConst.BLANK_SCHEMA] | None = None, cache: int | None = None, order: bool | None = None, data_type: _TypeEngineArgument[int] | None = None, optional: bool = False, quote: bool | None = None, metadata: MetaData | None = None, quote_schema: bool | None = None, for_update: bool = False) None

Construct a Sequence object.

Parameters:
  • name – the name of the sequence.

  • start

    the starting index of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “START WITH” clause. If None, the clause is omitted, which on most platforms indicates a starting value of 1.

    Changed in version 2.0: The Sequence.start parameter is required in order to have DDL emit “START WITH”. This is a reversal of a change made in version 1.4 which would implicitly render “START WITH 1” if the Sequence.start were not included. See The Sequence construct reverts to not having any explicit default “start” value; impacts MS SQL Server for more detail.

  • increment – the increment value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “INCREMENT BY” clause. If None, the clause is omitted, which on most platforms indicates an increment of 1.

  • minvalue – the minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “MINVALUE” clause. If None, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively.

  • maxvalue – the maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “MAXVALUE” clause. If None, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively.

  • nominvalue – no minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “NO MINVALUE” clause. If None, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively.

  • nomaxvalue – no maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the “NO MAXVALUE” clause. If None, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively.

  • cycle – allows the sequence to wrap around when the maxvalue or minvalue has been reached by an ascending or descending sequence respectively. This value is used when the CREATE SEQUENCE command is emitted to the database as the “CYCLE” clause. If the limit is reached, the next number generated will be the minvalue or maxvalue, respectively. If cycle=False (the default) any calls to nextval after the sequence has reached its maximum value will return an error.

  • schema – optional schema name for the sequence, if located in a schema other than the default. The rules for selecting the schema name when a MetaData is also present are the same as that of Table.schema.

  • cache – optional integer value; number of future values in the sequence which are calculated in advance. Renders the CACHE keyword understood by Oracle and PostgreSQL.

  • order – optional boolean value; if True, renders the ORDER keyword, understood by Oracle, indicating the sequence is definitively ordered. May be necessary to provide deterministic ordering using Oracle RAC.

  • data_type

    The type to be returned by the sequence, for dialects that allow us to choose between INTEGER, BIGINT, etc. (e.g., mssql).

    New in version 1.4.0.

  • optional – boolean value, when True, indicates that this Sequence object only needs to be explicitly generated on backends that don’t provide another way to generate primary key identifiers. Currently, it essentially means, “don’t create this sequence on the PostgreSQL backend, where the SERIAL keyword creates a sequence for us automatically”.

  • quote – boolean value, when True or False, explicitly forces quoting of the Sequence.name on or off. When left at its default of None, normal quoting rules based on casing and reserved words take place.

  • quote_schema – Set the quoting preferences for the schema name.

  • metadata

    optional MetaData object which this Sequence will be associated with. A Sequence that is associated with a MetaData gains the following capabilities:

    The above behaviors can only occur if the Sequence is explicitly associated with the MetaData via this parameter.

    See also

    Associating a Sequence with the MetaData - full discussion of the Sequence.metadata parameter.

  • for_update – Indicates this Sequence, when associated with a Column, should be invoked for UPDATE statements on that column’s table, rather than for INSERT statements, when no value is otherwise present for that column in the statement.

method sqlalchemy.schema.Sequence.create(bind: _CreateDropBind, checkfirst: bool = True) None

Creates this sequence in the database.

method sqlalchemy.schema.Sequence.drop(bind: _CreateDropBind, checkfirst: bool = True) None

Drops this sequence from the database.

method sqlalchemy.schema.Sequence.next_value() Function[int]

Return a next_value function element which will render the appropriate increment function for this Sequence within any SQL expression.

class sqlalchemy.schema.Identity

Defines an identity column, i.e. “GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY” syntax.

The Identity construct is an inline construct added to the argument list of a Column object:

from sqlalchemy import Identity

Table('foo', metadata_obj,
    Column('id', Integer, Identity())
    Column('description', Text),
)

See the linked documentation below for complete details.

New in version 1.4.

Members

__init__(), copy()

Class signature

class sqlalchemy.schema.Identity (sqlalchemy.schema.IdentityOptions, sqlalchemy.schema.FetchedValue, sqlalchemy.schema.SchemaItem)

method sqlalchemy.schema.Identity.__init__(always: bool = False, on_null: bool | None = None, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, cache: int | None = None, order: bool | None = None) None

Construct a GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY DDL construct to accompany a Column.

See the Sequence documentation for a complete description of most parameters.

Note

MSSQL supports this construct as the preferred alternative to generate an IDENTITY on a column, but it uses non standard syntax that only support Identity.start and Identity.increment. All other parameters are ignored.

Parameters:
  • always – A boolean, that indicates the type of identity column. If False is specified, the default, then the user-specified value takes precedence. If True is specified, a user-specified value is not accepted ( on some backends, like PostgreSQL, OVERRIDING SYSTEM VALUE, or similar, may be specified in an INSERT to override the sequence value). Some backends also have a default value for this parameter, None can be used to omit rendering this part in the DDL. It will be treated as False if a backend does not have a default value.

  • on_null – Set to True to specify ON NULL in conjunction with a always=False identity column. This option is only supported on some backends, like Oracle.

  • start – the starting index of the sequence.

  • increment – the increment value of the sequence.

  • minvalue – the minimum value of the sequence.

  • maxvalue – the maximum value of the sequence.

  • nominvalue – no minimum value of the sequence.

  • nomaxvalue – no maximum value of the sequence.

  • cycle – allows the sequence to wrap around when the maxvalue or minvalue has been reached.

  • cache – optional integer value; number of future values in the sequence which are calculated in advance.

  • order – optional boolean value; if true, renders the ORDER keyword.

method sqlalchemy.schema.Identity.copy(**kw: Any) Identity

Deprecated since version 1.4: The Identity.copy() method is deprecated and will be removed in a future release.