Autocommit¶
These examples are meant to highlight best practices and allow users to explore the
difference between having AUTOCOMMIT enabled versus disabled.
Throughout our examples, we use engine.begin(). Code inside of a with-block using
engine.begin() will behave the same whether AUTOCOMMIT
is enabled (y) or disabled (n). This is because engine.begin() automatically
issues a COMMIT when the block successfully finished or a ROLLBACK if it fails.
For any basic database modifications, the recommended best practice is to use
engine.begin(). This is to ensure that the objects are in the desired state before
performing further manipulation steps. While it is possible to use engine.connect()
instead, when AUTOCOMMIT is disabled, you must manually, inside of the with-block,
call commit(). For a more nuanced discussion, see Connection Management in SQLAlchemy.
To explore what changes when AUTOCOMMIT is set to n, you can:
Modify your configuration file, as described on Connection Configuration, to set
"AUTOCOMMIT":"n".Modify the code in the examples to use
engine.connect()instead ofengine.begin().Try to execute the examples and see what happens. You should get failures, as
engine.connect()withoutAUTOCOMMITrequires you to manually callconn.commit()as needed.Add
conn.commit()to the examples and try to execute them. They should now pass.
Note
The examples on this page are presented in sections, but they are all part
of the same module examples/features/specific_focuses/_1_autocommit.py.
They are broken up here to provide further information and context. Please
ensure that you read and execute the parts in order.
Data Definition Language (DDL)¶
from sqlalchemy import text
from examples.config import (
DEFAULT_SCHEMA_NAME,
ENGINE,
SQL_ALCHEMY,
)
# 0. Ensure that the schema exists
SQL_ALCHEMY.create_schema(engine=ENGINE, schema=DEFAULT_SCHEMA_NAME)
# 1. Data Definition Language (DDL)
TABLE_NAME = "HEX_LOOKUP"
create_hex_table = f"""
CREATE OR REPLACE TABLE {DEFAULT_SCHEMA_NAME}.{TABLE_NAME} (
id INTEGER IDENTITY PRIMARY KEY,
hex_code CHAR(6) NOT NULL
);
"""
with ENGINE.begin() as conn:
conn.execute(text(create_hex_table))
It is recommended to use engine.begin() for DDL statements.
Note
Note that IDENTITY
(an Exasol Database keyword)
must be included for the ID to autoincrement. This is not required for the
examples given in Basic Operations or ORM, where SQLAlchemy
generates the required SQL statement for the Exasol database instance.
Data Query Language (DQL)¶
# 2. Data Query Language (DQL)
query = f"""
SELECT *
FROM SYS.EXA_ALL_TABLES
WHERE TABLE_SCHEMA = '{DEFAULT_SCHEMA_NAME}'
AND TABLE_NAME = '{TABLE_NAME}'
"""
with ENGINE.connect() as conn:
results = conn.execute(text(query)).fetchall()
# conn.commit() is never needed for DQL
print(f"Table search result: {results}")
Typically, SELECT is considered the only member of DQL. In such use cases, no data
manipulations are occurring, so no manual commits need to be made. As such,
this code works and should stay the same regardless of whether AUTOCOMMIT is
enabled or disabled.
Data Manipulation Language (DML)¶
# 3. Data Manipulation Language (DML)
hex_data = [{"hex_code": "FF5733"}, {"hex_code": "33FF57"}, {"hex_code": "3357FF"}]
insert_statement = (
f"INSERT INTO {DEFAULT_SCHEMA_NAME}.{TABLE_NAME} " f"(hex_code) VALUES (:hex_code)"
)
with ENGINE.begin() as conn:
conn.execute(text(insert_statement), hex_data)
# if `ENGINE.connect()` were used instead of `ENGINE.begin()` and
# "AUTOCOMMIT" were disabled, you MUST include a `conn.commit()`
# for the change to be persisted; otherwise, no results will be
# found in #4,
# 4. DQL
select_statement = f"SELECT * FROM {DEFAULT_SCHEMA_NAME}.{TABLE_NAME}"
with ENGINE.connect() as conn:
result = conn.execute(text(select_statement)).fetchall()
print(f"Number of entries: {len(result)}")
for row in result:
print(row)
Like the Data Definition Language (DDL) example, it is preferred here to use begin() in the with-block.
This behaves the same whether AUTOCOMMIT is enabled or disabled. For a
more nuanced discussion, see Connection Management in SQLAlchemy.
Connection Management in SQLAlchemy¶
The begin() Method¶
The begin() method provides a transactional boundary. It is the safest choice
for an operation that modifies the database.
Scenario |
Description |
|---|---|
DDL |
Use for |
DML |
Ideal for |
Auto-Rollback |
If your code fails mid-block, SQLAlchemy automatically reverts any partial changes. |
The connect() Method¶
The connect() method provides a raw connection. It offers granular control but
places the responsibility of transaction management on the user.
When AUTOCOMMIT is enabled, using connect() ensures that each statement is
finalised by the database as soon as it is executed. If AUTOCOMMIT is disabled,
then you must manually use commit.
Scenario |
Description |
|---|---|
DQL |
Best for |
DML |
Use if you need to commit specific parts of a long-running script at different times. |
Performance Tuning |
Avoids the overhead of starting a transaction block when only reading data. |