Колонки INSERT/UPDATE по умолчанию

Колонки INSERT и UPDATE по умолчанию относятся к функциям, которые создают значение по умолчанию для определенного столбца в строке в процессе выполнения оператора INSERT или UPDATE для этой строки, в случае, когда никакое значение не было предоставлено оператору INSERT или UPDATE для этого столбца. То есть, если в таблице есть столбец «timestamp», и выполняется оператор INSERT, который не включает значение для этого столбца, то по умолчанию INSERT создаст новое значение, например, текущее время, которое будет использоваться в качестве значения для вставки в столбец «timestamp». Если оператор до включает значение для этого столбца, то умолчание не происходит.

Значения по умолчанию для столбцов могут быть функциями или постоянными значениями на стороне сервера, которые определяются в базе данных вместе со схемой в DDL, или как SQL выражения, которые отображаются непосредственно в операторе INSERT или UPDATE, создаваемом SQLAlchemy; они также могут быть функциями или постоянными значениями Python на стороне клиента, которые вызываются SQLAlchemy перед передачей данных в базу данных.

Примечание

Обработчик столбцов по умолчанию не следует путать с конструкцией, которая перехватывает и изменяет входящие значения для операторов INSERT и UPDATE, которые предоставляются оператору при его вызове. Это известно как data marshalling, когда значение столбца модифицируется каким-либо образом приложением перед отправкой в базу данных. SQLAlchemy предоставляет несколько способов достижения этого, которые включают использование custom datatypes, SQL execution events и в ORM custom validators, а также attribute events. Столбцы по умолчанию используются только тогда, когда нет значения для столбца в операторе SQL DML.

SQLAlchemy предоставляет ряд возможностей относительно функций генерации по умолчанию, которые выполняются для непредставленных значений во время выполнения операторов INSERT и UPDATE. Опции включают:

  • Скалярные значения, используемые по умолчанию во время операций INSERT и UPDATE

  • Функции Python, которые выполняются при операциях INSERT и UPDATE

  • SQL-выражения, которые встраиваются в операторы INSERT (или в некоторых случаях выполняются заранее)

  • Выражения SQL, которые встраиваются в операторы UPDATE

  • Значения по умолчанию на стороне сервера, используемые при INSERT

  • Маркеры для триггеров на стороне сервера, используемых во время UPDATE

Общее правило для всех параметров вставки/обновления по умолчанию заключается в том, что они вступают в силу, только если в качестве параметра execute() не передано значение для конкретного столбца; в противном случае используется заданное значение.

Скалярные значения по умолчанию

Самый простой вид значения по умолчанию - это скалярное значение, используемое в качестве значения по умолчанию для столбца:

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

Выше, значение «12» будет привязано в качестве значения столбца при INSERT, если не указано другое значение.

Скалярное значение также может быть связано с оператором UPDATE, хотя это не очень распространено (поскольку операторы UPDATE обычно ищут динамические значения по умолчанию):

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

Функции, исполняемые в Python

Аргументы ключевых слов 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 в большинстве случаев будет использовать эти возможности автоматически. Смотрите документацию API для Column, включая флаг Column.autoincrement, а также раздел 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),
)

Когда выполняется оператор обновления и не передается значение для last_updated, выполняется Python-функция datetime.datetime.now(), а ее возвращаемое значение используется в качестве значения для last_updated. Обратите внимание, что мы предоставляем now как саму функцию, не вызывая ее (т.е. после нее нет скобок) - SQLAlchemy выполнит функцию в момент выполнения оператора.

Контекстно-зависимые функции по умолчанию

Функции Python, используемые Column.default и Column.onupdate, также могут использовать контекст текущего оператора для определения значения. Контекст» оператора - это внутренний объект 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),
)

Приведенная выше функция генерации по умолчанию применяется таким образом, что она будет выполняться для всех операторов INSERT и UPDATE, в которых значение для counter_plus_twelve не было предоставлено, и значение будет равно значению, которое присутствует при выполнении для столбца counter плюс число 12.

Для одного оператора, выполняемого в стиле «executemany», например, с несколькими наборами параметров, переданных в Connection.execute(), пользовательская функция вызывается один раз для каждого набора параметров. В случае использования многозначной конструкции Insert (например, с более чем одним предложением VALUES, заданным с помощью метода Insert.values()) пользовательская функция также вызывается один раз для каждого набора параметров.

Когда функция вызывается, специальный метод DefaultExecutionContext.get_current_parameters() доступен из объекта контекста (подкласс DefaultExecutionContext). Этот метод возвращает словарь значений столбцов-ключей-значений, который представляет полный набор значений для оператора INSERT или UPDATE. В случае многозначной конструкции INSERT подмножество параметров, соответствующее отдельному предложению VALUES, выделяется из полного словаря параметров и возвращается отдельно.

Добавлено в версии 1.2: Добавлен метод DefaultExecutionContext.get_current_parameters(), который улучшает все еще существующий атрибут DefaultExecutionContext.current_parameters, предлагая услугу организации нескольких предложений VALUES в отдельные словари параметров.

Выражения SQL, вызываемые клиентом

Ключевые слова Column.default и Column.onupdate также могут передавать 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()),
)

Выше, столбец create_date будет заполнен результатом SQL-функции now() (которая, в зависимости от бэкенда, компилируется в NOW() или CURRENT_TIMESTAMP в большинстве случаев) при выполнении оператора INSERT, а столбец key - результатом подзапроса SELECT из другой таблицы. Столбец last_modified будет заполнен значением функции SQL UTC_TIMESTAMP() MySQL при выполнении оператора UPDATE для этой таблицы.

Примечание

При использовании функций SQL с помощью конструкции func мы «вызываем» именованную функцию, например, с помощью круглых скобок, как в func.now(). Это отличается от ситуации, когда мы указываем вызываемую функцию в Python по умолчанию, например datetime.datetime, где мы передаем саму функцию, но не вызываем ее сами. В случае функции SQL вызов func.now() возвращает объект выражения SQL, который преобразует функцию «NOW» в испускаемый SQL.

SQL-выражения по умолчанию и обновления, указанные в Column.default и Column.onupdate, вызываются SQLAlchemy явно при выполнении оператора INSERT или UPDATE, обычно отображаются в строке оператора DML, за исключением некоторых случаев, перечисленных ниже. Это отличается от умолчаний «на стороне сервера», которые являются частью определения DDL таблицы, например, как часть оператора «CREATE TABLE», которые, вероятно, более распространены. Об умолчаниях на стороне сервера см. следующий раздел Выражения по умолчанию DDL-Explicit, вызываемые сервером.

Когда SQL-выражение, обозначенное Column.default, используется с колонками первичного ключа, есть некоторые случаи, когда SQLAlchemy должна «предварительно выполнить» SQL-функцию генерации по умолчанию, то есть она вызывается в отдельном операторе SELECT, а полученное значение передается в качестве параметра в INSERT. Это происходит только для столбцов с первичным ключом для оператора INSERT, которому предлагается вернуть значение этого первичного ключа, где RETURNING или cursor.lastrowid не могут быть использованы. Конструкция Insert, в которой указан флаг insert.inline, всегда выводит выражения по умолчанию в строку.

Когда утверждение выполняется с одним набором параметров (то есть, это не выполнение в стиле «executemany»), возвращаемый CursorResult будет содержать коллекцию, доступную через CursorResult.postfetch_cols(), которая содержит список всех объектов Column, которые имели inline-выполнение по умолчанию. Аналогично, все параметры, которые были связаны с оператором, включая все выражения Python и SQL, которые были предварительно выполнены, присутствуют в коллекциях CursorResult.last_inserted_params() или CursorResult.last_updated_params() на CursorResult. Коллекция CursorResult.inserted_primary_key содержит список значений первичного ключа для вставленной строки (список, чтобы первичные ключи с одним столбцом и составным столбцом были представлены в одинаковом формате).

Выражения по умолчанию DDL-Explicit, вызываемые сервером

Вариантом выражения SQL по умолчанию является Column.server_default, которое помещается в оператор CREATE TABLE во время операции Table.create():

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 - функцию SQL (SYSDATE в приведенном выше примере) и постоянное значение на стороне сервера (целое число «0» в приведенном выше примере). Рекомендуется использовать конструкцию text() для любых буквальных значений SQL, а не передавать необработанное значение, так как SQLAlchemy обычно не выполняет кавычки или экранирование для этих значений.

Как и генерируемые клиентом выражения, Column.server_default может использовать выражения SQL в целом, однако ожидается, что это будут простые функции и выражения, а не более сложные случаи, такие как встроенный SELECT.

Маркировка неявно генерируемых значений, временных меток и триггерных столбцов

Колонки, которые генерируют новое значение при 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 не влияет на отображаемый DDL для CREATE TABLE. Вместо этого он помечает столбец как тот, который будет иметь новое значение, заполненное базой данных в процессе выполнения оператора INSERT или UPDATE, а для поддерживающих баз данных может использоваться для указания того, что столбец должен быть частью предложения RETURNING или OUTPUT для оператора. Такие инструменты, как SQLAlchemy ORM, используют этот маркер для того, чтобы знать, как получить значение столбца после такой операции. В частности, метод ValuesBase.return_defaults() можно использовать с конструкцией Insert или Update, чтобы указать, что эти значения должны быть возвращены.

Подробнее об использовании FetchedValue с ORM см. в разделе Получение генерируемых сервером значений по умолчанию.

Предупреждение

Директива Column.server_onupdate **в настоящее время не производит предложение MySQL «ON UPDATE CURRENT_TIMESTAMP()». Смотрите Рендеринг ON UPDATE CURRENT TIMESTAMP для MySQL / MariaDB’s explicit_defaults_for_timestamp для получения информации о том, как производить это предложение.

Определение последовательностей

SQLAlchemy представляет последовательности баз данных с помощью объекта Sequence, который считается особым случаем «столбца по умолчанию». Он действует только для баз данных, которые имеют явную поддержку последовательностей, что среди диалектов SQLAlchemy включает PostgreSQL, Oracle, MS SQL Server и MariaDB. В остальных случаях объект Sequence игнорируется.

Совет

В новых движках баз данных для генерации целочисленных значений первичного ключа, скорее всего, следует предпочесть конструкцию Identity, а не Sequence. Смотрите раздел Колонки идентичности (генерируются { ВСЕГДА | ПО ОПРЕДЕЛЕНИЮ } КАК ИДЕНТИЧНОСТЬ) для справки об этой конструкции.

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)
)

Совет

При использовании таблиц с явными именами схем (подробно описано в Указание имени схемы), настроенная схема Table не автоматически разделяется встроенной Sequence, вместо этого укажите Sequence.schema:

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

Sequence также может быть сделано так, чтобы автоматически использовать настройку MetaData.schema на используемом MetaData; подробнее см. в Ассоциирование последовательности с метаданными.

Когда конструкции DML Insert вызываются против таблицы cartitems, без явного значения, переданного для столбца cart_id, последовательность 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 с помощью атрибута CursorResult.inserted_primary_key.

Когда Sequence связан с Column как его Python-side генератор по умолчанию, Sequence будет также подвержен DDL «CREATE SEQUENCE» и «DROP SEQUENCE», когда аналогичный DDL будет создан для принадлежащего ему Table, например, при использовании MetaData.create_all() для генерации DDL для серии таблиц.

Параметр Sequence также может быть связан с конструкцией MetaData напрямую. Это позволяет использовать Sequence более чем в одном Table одновременно, а также наследовать параметр MetaData.schema. Подробнее см. в разделе Ассоциирование последовательности с метаданными.

Ассоциирование последовательности с колонкой SERIAL

Тип данных SERIAL в PostgreSQL - это автоинкрементирующий тип, который подразумевает неявное создание последовательности PostgreSQL при создании CREATE TABLE. Конструкция Sequence, когда указывается для Column, может показать, что ее не следует использовать в данном конкретном случае, указав значение True для параметра Sequence.optional. Это позволяет использовать данную конструкцию 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()),
)

В приведенном выше примере CREATE TABLE для PostgreSQL будет использоваться тип данных SERIAL для столбца cart_id, а последовательность cart_id_seq будет проигнорирована. Однако в Oracle последовательность cart_id_seq будет создана явно.

Совет

Это конкретное взаимодействие SERIAL и SEQUENCE достаточно унаследовано, и, как и в других случаях, использование Identity вместо этого упростит операцию до простого использования IDENTITY на всех поддерживаемых бэкендах.

Выполнение последовательности в автономном режиме

SEQUENCE является объектом схемы первого класса в SQL и может использоваться для самостоятельной генерации значений в базе данных. Если у вас есть объект Sequence, его можно вызвать с помощью инструкции «следующее значение», передав его непосредственно в метод выполнения SQL:

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

Чтобы встроить функцию «следующего значения» Sequence внутрь SQL-оператора, например SELECT или INSERT, используйте метод Sequence.next_value(), который во время компиляции оператора выдаст SQL-функцию, подходящую для целевого бэкенда:

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

Ассоциирование последовательности с метаданными

Для Sequence, который должен быть связан с произвольными Table объектами, 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 позволяет реализовать следующие модели поведения:

Назначение последовательности в качестве значения по умолчанию на стороне сервера

Примечание

Известно, что следующая техника работает только с базой данных PostgreSQL. Она не работает с Oracle.

В предыдущих разделах показано, как связать Sequence с Column в качестве генератора по умолчанию на стороне Python:

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

В приведенном выше случае Sequence будет автоматически подвергаться DDL CREATE SEQUENCE / DROP SEQUENCE, когда связанный Table будет подвергаться CREATE / DROP. Однако, последовательность не будет присутствовать в качестве значения по умолчанию на стороне сервера для столбца при создании CREATE TABLE.

Если мы хотим, чтобы последовательность использовалась по умолчанию на стороне сервера, то есть выполнялась, даже если мы подаем команды INSERT на таблицу из командной строки SQL, мы можем использовать параметр Column.server_default в сочетании с функцией генерации значений последовательности, доступной из метода Sequence.next_value(). Ниже показано, как один и тот же Sequence ассоциируется с 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)
)

Размещение Sequence как в контекстах генерации по умолчанию на стороне Python, так и на стороне сервера гарантирует, что логика «выборки первичного ключа» работает во всех случаях. Как правило, базы данных с поддержкой последовательности также поддерживают RETURNING для операторов INSERT, что автоматически используется SQLAlchemy при генерации этого оператора. Однако если RETURNING не используется для конкретной вставки, то SQLAlchemy предпочтет «предварительно выполнить» последовательность вне самого оператора INSERT, что работает только в том случае, если последовательность включена в качестве функции генератора по умолчанию на стороне Python.

Пример также напрямую связывает Sequence с вложенным MetaData, что опять же гарантирует, что Sequence полностью связан с параметрами коллекции MetaData, включая схему по умолчанию, если таковая имеется.

См.также

Последовательности/СЕРИАЛ/ИДЕНТИЧНОСТЬ - в документации по диалекту PostgreSQL

поддержка возврата - в документации по диалекту Oracle

Вычисляемые столбцы (генерируются ВСЕГДА КАК)

Добавлено в версии 1.3.11.

Конструкция Computed позволяет объявить Column в DDL как столбец «GENERATED ALWAYS AS», то есть такой, значение которого вычисляется сервером базы данных. Эта конструкция принимает SQL-выражение, обычно объявляемое текстуально с помощью строки или конструкции text(), аналогично конструкции CheckConstraint. Выражение 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")),
)

DDL для таблицы square при выполнении на бэкенде PostgreSQL 12 будет выглядеть следующим образом:

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, или оно вычисляется при получении, является деталью реализации базы данных; первый вариант известен как «хранимый», а второй - как «виртуальный». Некоторые реализации баз данных поддерживают оба варианта, а некоторые - только один или другой. Необязательный флаг Computed.persisted может быть указан как True или False, чтобы указать, должно ли ключевое слово «STORED» или «VIRTUAL» отображаться в DDL, однако это вызовет ошибку, если ключевое слово не поддерживается целевым бэкендом; если флаг не установлен, будет использоваться рабочее значение по умолчанию для целевого бэкенда.

Конструкция Computed является подклассом объекта FetchedValue и устанавливает себя в качестве генератора «server default» и «server onupdate» для целевого Column, что означает, что он будет рассматриваться как генерирующий столбец по умолчанию при генерации операторов INSERT и UPDATE, а также что он будет извлекаться как генерирующий столбец при использовании ORM. Это включает в себя то, что он будет частью условия RETURNING в базе данных для баз данных, которые поддерживают RETURNING, и сгенерированные значения будут извлекаться с нетерпением.

Примечание

Колонка Column, определенная с помощью конструкции Computed, не может хранить никакое значение, кроме того, которое сервер применяет к ней; поведение SQLAlchemy при передаче значения для такой колонки для записи в INSERT или UPDATE в настоящее время заключается в том, что значение будет проигнорировано.

«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.

См.также

Computed

Колонки идентичности (генерируются { ВСЕГДА | ПО ОПРЕДЕЛЕНИЮ } КАК ИДЕНТИЧНОСТЬ)

Добавлено в версии 1.4.

Конструкция Identity позволяет Column объявить столбец идентичности и представить его в DDL как «GENERATED { ALWAYS | BY DEFAULT } AS 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),
)

DDL для таблицы data при выполнении на бэкенде PostgreSQL 12 будет выглядеть следующим образом:

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.always в True в конструкции Identity. Обновление предыдущего примера для включения этого параметра приведет к созданию следующего DDL:

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

Конструкция Identity является подклассом объекта FetchedValue и устанавливает себя в качестве генератора «по умолчанию сервера» для целевого Column, что означает, что он будет рассматриваться как генерирующий столбец по умолчанию при генерации операторов INSERT, а также что он будет извлекаться как генерирующий столбец при использовании ORM. Это включает в себя то, что он будет частью условия RETURNING базы данных для баз данных, которые поддерживают RETURNING, и сгенерированные значения будут извлекаться с нетерпением.

В настоящее время конструкция Identity поддерживается:

  • PostgreSQL начиная с версии 10.

  • Oracle начиная с версии 12. Он также поддерживает передачу always=None для включения режима генерации по умолчанию и параметра on_null=True для указания «ON NULL» в сочетании со столбцом идентификации «BY DEFAULT».

  • Microsoft SQL Server. MSSQL использует собственный синтаксис, который поддерживает только параметры start и increment, а все остальные игнорирует.

Когда Identity используется с неподдерживаемым бэкендом, он игнорируется, и используется стандартная логика SQLAlchemy для автоинкрементных колонок.

Возникает ошибка, если Column указывает как Identity, так и устанавливает Column.autoincrement в False.

См.также

Identity

API объектов по умолчанию

Object Name Description

ColumnDefault

Обычное значение по умолчанию для столбца.

Computed

Определяет генерируемый столбец, т.е. синтаксис «GENERATED ALWAYS AS».

DefaultClause

Значение столбца DEFAULT, определенное в DDL.

DefaultGenerator

Базовый класс для значений столбцов по умолчанию.

FetchedValue

Маркер для прозрачного умолчания на стороне базы данных.

Identity

Определяет столбец идентичности, т.е. «GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY».

Sequence

Представляет собой именованную последовательность базы данных.

class sqlalchemy.schema.Computed

Определяет генерируемый столбец, т.е. синтаксис «GENERATED ALWAYS AS».

Конструкция Computed является встроенной конструкцией, добавляемой в список аргументов объекта Column:

from sqlalchemy import Computed

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

Подробную информацию см. в документации по ссылке ниже.

Добавлено в версии 1.3.11.

Members

__init__(), copy()

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

Создайте конструкцию GENERATED ALWAYS AS DDL для сопровождения Column.

Параметры:
  • sqltext – Строка, содержащая выражение генерации столбцов, которое будет использоваться дословно, или конструкцию выражения SQL, например, объект text(). Если объект задан в виде строки, он преобразуется в объект text(). … предупреждение:: Аргумент Computed.sqltext в Computed может быть передан как строковый аргумент Python, который будет рассматриваться как доверенный SQL-текст и будет преобразован, как указано. НЕ ПЕРЕДАВАЙТЕ НЕДОВЕРЕННЫЙ ВВОД В ЭТОТ ПАРАМЕТР.

  • persisted – Необязательный, управляет тем, как этот столбец должен быть сохранен в базе данных. Возможные значения: * None, по умолчанию, будет использоваться персистентность по умолчанию, определенная базой данных. * True, будет использоваться GENERATED ALWAYS AS ... STORED, или эквивалент для целевой базы данных, если поддерживается. * False, будет отображаться GENERATED ALWAYS AS ... VIRTUAL, или эквивалент для целевой базы данных, если поддерживается. Указание True или False может привести к ошибке при передаче DDL в целевую базу данных, если база данных не поддерживает эту опцию персистентности. Если оставить значение этого параметра по умолчанию None, то гарантируется успех для всех баз данных, поддерживающих GENERATED ALWAYS AS.

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

Не рекомендуется, начиная с версии 1.4: Метод Computed.copy() является устаревшим и будет удален в одном из будущих выпусков.

class sqlalchemy.schema.ColumnDefault

Обычное значение по умолчанию для столбца.

Это может соответствовать константе, вызываемой функции или предложению SQL.

ColumnDefault генерируется автоматически всякий раз, когда используются аргументы default, onupdate из Column. Аргумент ColumnDefault также может быть передан позиционно.

Например, следующее:

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

Это эквивалентно:

Column('foo', Integer, ColumnDefault(50))

Классная подпись

класс sqlalchemy.schema.ColumnDefault (sqlalchemy.schema.DefaultGenerator, abc.ABC)

class sqlalchemy.schema.DefaultClause

Значение столбца DEFAULT, определенное в DDL.

DefaultClause - это FetchedValue, который также генерирует предложение «DEFAULT», когда выдается «CREATE TABLE».

DefaultClause генерируется автоматически всякий раз, когда используются аргументы server_default, server_onupdate из Column. Аргумент DefaultClause также может быть передан позиционно.

Например, следующее:

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

Это эквивалентно:

Column('foo', Integer, DefaultClause("50"))

Классная подпись

класс sqlalchemy.schema.DefaultClause (sqlalchemy.schema.FetchedValue)

class sqlalchemy.schema.DefaultGenerator

Базовый класс для значений столбцов по умолчанию.

Этот объект присутствует только в column.default или column.onupdate. Он не действителен в качестве значения по умолчанию на сервере.

class sqlalchemy.schema.FetchedValue

Маркер для прозрачного умолчания на стороне базы данных.

Используйте FetchedValue, если база данных сконфигурирована для обеспечения некоторого автоматического значения по умолчанию для столбца.

Например:

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

Указывает на то, что какой-то триггер или генератор по умолчанию создаст новое значение для столбца foo во время INSERT.

Классная подпись

класс sqlalchemy.schema.FetchedValue (sqlalchemy.sql.expression.SchemaEventTarget)

class sqlalchemy.schema.Sequence

Представляет собой именованную последовательность базы данных.

Объект Sequence представляет имя и конфигурационные параметры последовательности базы данных. Он также представляет собой конструкцию, которая может быть «выполнена» SQLAlchemy Engine или Connection, создавая соответствующую функцию «следующего значения» для целевой базы данных и возвращая результат.

Sequence обычно ассоциируется с колонкой первичного ключа:

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

Когда CREATE TABLE выдается для вышеуказанной конструкции Table, если целевая платформа поддерживает последовательности, будет выдан также оператор CREATE SEQUENCE. Для платформ, не поддерживающих последовательности, конструкция Sequence игнорируется.

Классная подпись

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

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

Создайте объект Sequence.

Параметры:
  • name – имя последовательности.

  • start – начальный индекс последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения условия «START WITH». Если None, то условие опускается, что на большинстве платформ означает начальное значение 1. … versionchanged:: 2.0 Параметр Sequence.start необходим для того, чтобы DDL выдавал «START WITH». Это отмена изменения, сделанного в версии 1.4, которое неявно выдавало «START WITH 1», если не был включен параметр Sequence.start. См. раздел Конструкция Sequence возвращается к отсутствию явного значения «start» по умолчанию; влияет на MS SQL Server для более подробной информации.

  • increment – значение инкремента последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения условия «INCREMENT BY». Если None, то условие опускается, что на большинстве платформ означает инкремент 1.

  • minvalue – минимальное значение последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения оговорки «MINVALUE». Если None, то условие опускается, что на большинстве платформ означает минимальное значение 1 и -2^63-1 для восходящей и нисходящей последовательностей, соответственно.

  • maxvalue – максимальное значение последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения оговорки «MAXVALUE». Если None, то условие опускается, что на большинстве платформ означает максимальное значение 2^63-1 и -1 для восходящей и нисходящей последовательностей, соответственно.

  • nominvalue – отсутствие минимального значения последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения оговорки «NO MINVALUE». Если None, то условие опускается, что на большинстве платформ означает минимальное значение 1 и -2^63-1 для восходящей и нисходящей последовательностей, соответственно.

  • nomaxvalue – нет максимального значения последовательности. Это значение используется при передаче в базу данных команды CREATE SEQUENCE в качестве значения оговорки «NO MAXVALUE». Если None, то условие опускается, что на большинстве платформ означает максимальное значение 2^63-1 и -1 для восходящей и нисходящей последовательностей, соответственно.

  • cycle – позволяет последовательности обернуться, когда максимальное или минимальное значение было достигнуто восходящей или нисходящей последовательностью соответственно. Это значение используется, когда команда CREATE SEQUENCE передается в базу данных в качестве условия «CYCLE». Если предел достигнут, то следующим генерируемым числом будет minvalue или maxvalue, соответственно. Если cycle=False (по умолчанию), любые вызовы nextval после достижения последовательностью максимального значения вернут ошибку.

  • schema – необязательное имя схемы для последовательности, если она расположена в схеме, отличной от схемы по умолчанию. Правила выбора имени схемы, когда присутствует MetaData, такие же, как и для Table.schema.

  • cache – необязательное целочисленное значение; количество будущих значений в последовательности, которые вычисляются заранее. Переводит ключевое слово CACHE, понятное Oracle и PostgreSQL.

  • order – необязательное булево значение; если True, выдает ключевое слово ORDER, понимаемое Oracle, указывая, что последовательность окончательно упорядочена. Может потребоваться для обеспечения детерминированного упорядочивания при использовании Oracle RAC.

  • data_type – Тип, возвращаемый последовательностью, для диалектов, позволяющих выбирать между INTEGER, BIGINT и т.д. (например, mssql). … версия добавлена:: 1.4.0

  • optional – булево значение, когда True, указывает, что этот объект Sequence должен быть явно создан только на бэкендах, которые не предоставляют другого способа создания идентификаторов первичных ключей. В настоящее время это означает, по сути, «не создавайте эту последовательность на бэкенде PostgreSQL, где ключевое слово SERIAL создает последовательность для нас автоматически».

  • quote – булево значение, когда True или False, явно включает или выключает цитирование Sequence.name. Если оставить значение по умолчанию None, то действуют обычные правила цитирования, основанные на кешировании и зарезервированных словах.

  • quote_schema – Установите предпочтения цитирования для имени schema.

  • metadata – необязательный объект MetaData, с которым будет ассоциирован данный Sequence. Sequence, связанный с MetaData, приобретает следующие возможности: * Sequence будет наследовать параметр MetaData.schema, указанный целевому MetaData, что влияет на создание CREATE / DROP DDL, если таковые имеются. * Методы Sequence.create() и Sequence.drop() автоматически используют движок, привязанный к объекту MetaData, если таковой имеется. * Методы MetaData.create_all() и MetaData.drop_all() будут выдавать CREATE / DROP для данного Sequence, даже если Sequence не связан ни с одним Table / Column, который является членом данного MetaData. Вышеописанное поведение может иметь место, только если Sequence явно ассоциирован с MetaData через этот параметр. … см. также:: Ассоциирование последовательности с метаданными - полное обсуждение параметра Sequence.metadata.

  • for_update – Указывает, что этот Sequence, когда он связан с Column, должен вызываться для операторов UPDATE для таблицы этого столбца, а не для операторов INSERT, когда в операторе нет значения для этого столбца.

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

Создает данную последовательность в базе данных.

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

Удаляет эту последовательность из базы данных.

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

Возвращает элемент функции next_value, который выводит соответствующую функцию инкремента для этого Sequence в любом выражении SQL.

class sqlalchemy.schema.Identity

Определяет столбец идентичности, т.е. «GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY».

Конструкция Identity является встроенной конструкцией, добавляемой в список аргументов объекта Column:

from sqlalchemy import Identity

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

Подробную информацию см. в документации по ссылке ниже.

Добавлено в версии 1.4.

Members

__init__(), copy()

Классная подпись

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

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

Создайте конструкцию GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY DDL для сопровождения Column.

Полное описание большинства параметров см. в документации Sequence.

Примечание

MSSQL поддерживает эту конструкцию как предпочтительную альтернативу для генерации IDENTITY для столбца, но она использует нестандартный синтаксис, который поддерживает только Identity.start и Identity.increment. Все остальные параметры игнорируются.

Параметры:
  • always – Булево значение, указывающее на тип столбца идентификации. Если указано False, что является значением по умолчанию, то указанное пользователем значение имеет приоритет. Если указано True, то значение, указанное пользователем, не принимается (в некоторых бэкендах, например PostgreSQL, в INSERT может быть указано OVERRIDING SYSTEM VALUE или аналогичное значение, чтобы отменить значение последовательности). Некоторые бэкенды также имеют значение по умолчанию для этого параметра, None можно использовать, чтобы не отображать эту часть в DDL. Если бэкенд не имеет значения по умолчанию, он будет рассматриваться как False.

  • on_null – Установите значение True, чтобы указать ON NULL в сочетании со столбцом идентификации always=False. Этот параметр поддерживается только в некоторых бэкендах, например в Oracle.

  • start – начальный индекс последовательности.

  • increment – значение приращения последовательности.

  • minvalue – минимальное значение последовательности.

  • maxvalue – максимальное значение последовательности.

  • nominvalue – нет минимального значения последовательности.

  • nomaxvalue – нет максимального значения последовательности.

  • cycle – позволяет обернуть последовательность, когда достигнуто максимальное или минимальное значение.

  • cache – необязательное целочисленное значение; количество будущих значений в последовательности, которые вычисляются заранее.

  • order – необязательное булево значение; если true, отображает ключевое слово ORDER.

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

Не рекомендуется, начиная с версии 1.4: Метод Identity.copy() является устаревшим и будет удален в одном из будущих выпусков.

Вернуться на верх