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
関数の now
を Column.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.default
と Column.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.default
と Column.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式を含む)は、 CursorResult
の CursorResult.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 を参照してください。
See also
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()),
)
上記の場合、テーブル cartitems
は cart_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
構文から利用できます。
Sequence
が Python側 のデフォルトジェネレータとして 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
オブジェクトは独立したスキーマ構成体として扱われ、単独で存在することも、テーブル間で共有されることもできます。
Sequence
を MetaData
と明示的に関連付けると、以下のような振る舞いが可能になります:
Sequence
はMetaData.schema
を継承します。
Associating a Sequence as the Server Side Default¶
Note
以下のテクニックは、PostgreSQLデータベースでのみ動作することが分かっています。Oracleでは動作しません。
これまでの節では、 Python側のデフォルトジェネレータ として、 Sequence
を Column
に関連付ける方法を説明してきました:
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
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.always
を True
に設定します。前の例を更新してこのパラメータを含めると、次の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は、
start
とincrement
パラメータのみをサポートし、他のパラメータをすべて無視するカスタム構文を使用します。
サポートされていないバックエンドで Identity
が使用された場合、これは無視され、カラムを自動的にインクリメントするデフォルトのSQLAlchemyロジックが使用されます。
Column
が Identity
を指定し、かつ Column.autoincrement
を False
に設定した場合、エラーが発生します。
See also
Default Objects API¶
Object Name | Description |
---|---|
A plain default value on a column. |
|
Defines a generated column, i.e. “GENERATED ALWAYS AS” syntax. |
|
A DDL-specified DEFAULT column value. |
|
Base class for column default values. |
|
A marker for a transparent database-side default. |
|
Defines an identity column, i.e. “GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY” syntax. |
|
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 aColumn
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
Class signature
class
sqlalchemy.schema.Computed
(sqlalchemy.schema.FetchedValue
,sqlalchemy.schema.SchemaItem
)-
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 atext()
object.Warning
The
Computed.sqltext
argument toComputed
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 renderGENERATED ALWAYS AS ... STORED
, or the equivalent for the target database if supported.False
, will renderGENERATED ALWAYS AS ... VIRTUAL
, or the equivalent for the target database if supported.
Specifying
True
orFalse
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 ofNone
is guaranteed to succeed for all databases that supportGENERATED 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.
-
method
- 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 thedefault
,onupdate
arguments ofColumn
are used. AColumnDefault
can be passed positionally as well.For example, the following:
Column('foo', Integer, default=50)
Is equivalent to:
Column('foo', Integer, ColumnDefault(50))
Class signature
class
sqlalchemy.schema.ColumnDefault
(sqlalchemy.schema.DefaultGenerator
,abc.ABC
)
- class sqlalchemy.schema.DefaultClause¶
A DDL-specified DEFAULT column value.
DefaultClause
is aFetchedValue
that also generates a “DEFAULT” clause when “CREATE TABLE” is emitted.DefaultClause
is generated automatically whenever theserver_default
,server_onupdate
arguments ofColumn
are used. ADefaultClause
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 signature
class
sqlalchemy.schema.DefaultClause
(sqlalchemy.schema.FetchedValue
)
- 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 signature
class
sqlalchemy.schema.DefaultGenerator
(sqlalchemy.sql.expression.Executable
,sqlalchemy.schema.SchemaItem
)
- 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 SQLAlchemyEngine
orConnection
, 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, theSequence
construct is ignored.Members
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 theSequence.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 ofTable.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 thisSequence
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
orFalse
, explicitly forces quoting of theSequence.name
on or off. When left at its default ofNone
, 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 thisSequence
will be associated with. ASequence
that is associated with aMetaData
gains the following capabilities:The
Sequence
will inherit theMetaData.schema
parameter specified to the targetMetaData
, which affects the production of CREATE / DROP DDL, if any.The
Sequence.create()
andSequence.drop()
methods automatically use the engine bound to theMetaData
object, if any.The
MetaData.create_all()
andMetaData.drop_all()
methods will emit CREATE / DROP for thisSequence
, even if theSequence
is not associated with anyTable
/Column
that’s a member of thisMetaData
.
The above behaviors can only occur if the
Sequence
is explicitly associated with theMetaData
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 aColumn
, 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 thisSequence
within any SQL expression.
-
method
- 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 aColumn
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
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
andIdentity.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. IfTrue
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 asFalse
if a backend does not have a default value.on_null¶ – Set to
True
to specify ON NULL in conjunction with aalways=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.
-
method