Snowflake SQLAlchemy Dialect
The Snowflake SQLAlchemy Dialect is a Python library that provides a SQLAlchemy dialect for connecting to Snowflake data warehouses. It functions as a bridge between SQLAlchemy applications and the Snowflake Connector for Python. The library is actively maintained with frequent releases, often multiple times per quarter, to introduce new features, improve compatibility, and address bug fixes.
Warnings
- breaking The default behavior of the division operator (`/`) in SnowflakeDialect changed in version 1.7.3. Previously, `/` was integer division; it is now float division, aligning with standard Python 3 behavior. Integer division is now `//`. A `force_div_is_floordiv` flag was added for backward compatibility, but it is slated for removal in future releases.
- gotcha Snowflake stores all case-insensitive object names (e.g., table, column names) in uppercase. SQLAlchemy, by default, considers lowercase object names as case-insensitive. This mismatch can lead to issues during schema reflection (e.g., `get_table_names`, `get_columns`) if object names are not consistently handled (e.g., quoted identifiers for case-sensitivity).
- gotcha It is critical to explicitly close connections (`connection.close()`) before disposing of the engine (`engine.dispose()`). Failing to do so can prevent the underlying Snowflake Connector for Python from properly closing sessions, leading to resource leaks or unexpected behavior.
- breaking Compatibility with `snowflake-connector-python` versions. For example, version 1.8.0 bumped the required `snowflake-connector-python` to be less than 5.0.0, and `v1.8.1` was yanked due to connector compatibility. Ensure your connector version is within the supported range for your `snowflake-sqlalchemy` version.
- gotcha Special characters like '%' or '@' in passwords or other connection parameters within a URL connection string must be URL-encoded to be parsed correctly by SQLAlchemy and the underlying connector.
- gotcha Schema reflection could cause crashes in version 1.9.0 when reflecting without specifying a schema, due to `None` arguments in internal schema resolution, or when `SHOW TABLES` returns unexpected results.
Install
-
pip install snowflake-sqlalchemy
Imports
- create_engine
from sqlalchemy import create_engine
- URL
from snowflake.sqlalchemy import URL
Quickstart
import os
from sqlalchemy import create_engine, text
from snowflake.sqlalchemy import URL
# Replace with your Snowflake credentials or set them as environment variables
SNOWFLAKE_ACCOUNT = os.environ.get('SNOWFLAKE_ACCOUNT', 'your_account_identifier')
SNOWFLAKE_USER = os.environ.get('SNOWFLAKE_USER', 'your_user_login_name')
SNOWFLAKE_PASSWORD = os.environ.get('SNOWFLAKE_PASSWORD', 'your_password')
SNOWFLAKE_WAREHOUSE = os.environ.get('SNOWFLAKE_WAREHOUSE', 'your_warehouse')
SNOWFLAKE_DATABASE = os.environ.get('SNOWFLAKE_DATABASE', 'your_database')
SNOWFLAKE_SCHEMA = os.environ.get('SNOWFLAKE_SCHEMA', 'your_schema')
try:
engine = create_engine(
URL(
account=SNOWFLAKE_ACCOUNT,
user=SNOWFLAKE_USER,
password=SNOWFLAKE_PASSWORD,
database=SNOWFLAKE_DATABASE,
schema=SNOWFLAKE_SCHEMA,
warehouse=SNOWFLAKE_WAREHOUSE
)
)
with engine.connect() as connection:
result = connection.execute(text('SELECT current_version()')).fetchone()
print(f"Connected to Snowflake. Current version: {result[0]}")
except Exception as e:
print(f"Error connecting to Snowflake: {e}")
finally:
if 'engine' in locals():
engine.dispose() # Ensures all connections are closed.