Skip to content

Commit 49f91de

Browse files
Update README.md with Custom Tables documentation (#552)
1 parent 140fec8 commit 49f91de

File tree

1 file changed

+144
-1
lines changed

1 file changed

+144
-1
lines changed

README.md

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,39 @@ Snowflake stores all case-insensitive object names in uppercase text. In contras
234234

235235
### Index Support
236236

237-
Snowflake does not utilize indexes, so neither does Snowflake SQLAlchemy.
237+
Indexes are supported only for Hybrid Tables in Snowflake SQLAlchemy. For more details on limitations and use cases, refer to the [Create Index documentation](https://docs.snowflake.com/en/sql-reference/constraints-indexes.html). You can create an index using the following methods:
238+
239+
#### Single Column Index
240+
241+
You can create a single column index by setting the `index=True` parameter on the column or by explicitly defining an `Index` object.
242+
243+
```python
244+
hybrid_test_table_1 = HybridTable(
245+
"table_name",
246+
metadata,
247+
Column("column1", Integer, primary_key=True),
248+
Column("column2", String, index=True),
249+
Index("index_1", "column1", "column2")
250+
)
251+
252+
metadata.create_all(engine_testaccount)
253+
```
254+
255+
#### Multi-Column Index
256+
257+
For multi-column indexes, you define the `Index` object specifying the columns that should be indexed.
258+
259+
```python
260+
hybrid_test_table_1 = HybridTable(
261+
"table_name",
262+
metadata,
263+
Column("column1", Integer, primary_key=True),
264+
Column("column2", String),
265+
Index("index_1", "column1", "column2")
266+
)
267+
268+
metadata.create_all(engine_testaccount)
269+
```
238270

239271
### Numpy Data Type Support
240272

@@ -461,6 +493,117 @@ copy_into = CopyIntoStorage(from_=users,
461493
connection.execute(copy_into)
462494
```
463495

496+
### Iceberg Table with Snowflake Catalog support
497+
498+
Snowflake SQLAlchemy supports Iceberg Tables with the Snowflake Catalog, along with various related parameters. For detailed information about Iceberg Tables, refer to the Snowflake [CREATE ICEBERG](https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table-snowflake) documentation.
499+
500+
To create an Iceberg Table using Snowflake SQLAlchemy, you can define the table using the SQLAlchemy Core syntax as follows:
501+
502+
```python
503+
table = IcebergTable(
504+
"myuser",
505+
metadata,
506+
Column("id", Integer, primary_key=True),
507+
Column("name", String),
508+
external_volume=external_volume_name,
509+
base_location="my_iceberg_table",
510+
as_query="SELECT * FROM table"
511+
)
512+
```
513+
514+
Alternatively, you can define the table using a declarative approach:
515+
516+
```python
517+
class MyUser(Base):
518+
__tablename__ = "myuser"
519+
520+
@classmethod
521+
def __table_cls__(cls, name, metadata, *arg, **kw):
522+
return IcebergTable(name, metadata, *arg, **kw)
523+
524+
__table_args__ = {
525+
"external_volume": "my_external_volume",
526+
"base_location": "my_iceberg_table",
527+
"as_query": "SELECT * FROM table",
528+
}
529+
530+
id = Column(Integer, primary_key=True)
531+
name = Column(String)
532+
```
533+
534+
### Hybrid Table support
535+
536+
Snowflake SQLAlchemy supports Hybrid Tables with indexes. For detailed information, refer to the Snowflake [CREATE HYBRID TABLE](https://docs.snowflake.com/en/sql-reference/sql/create-hybrid-table) documentation.
537+
538+
To create a Hybrid Table and add an index, you can use the SQLAlchemy Core syntax as follows:
539+
540+
```python
541+
table = HybridTable(
542+
"myuser",
543+
metadata,
544+
Column("id", Integer, primary_key=True),
545+
Column("name", String),
546+
Index("idx_name", "name")
547+
)
548+
```
549+
550+
Alternatively, you can define the table using the declarative approach:
551+
552+
```python
553+
class MyUser(Base):
554+
__tablename__ = "myuser"
555+
556+
@classmethod
557+
def __table_cls__(cls, name, metadata, *arg, **kw):
558+
return HybridTable(name, metadata, *arg, **kw)
559+
560+
__table_args__ = (
561+
Index("idx_name", "name"),
562+
)
563+
564+
id = Column(Integer, primary_key=True)
565+
name = Column(String)
566+
```
567+
568+
### Dynamic Tables support
569+
570+
Snowflake SQLAlchemy supports Dynamic Tables. For detailed information, refer to the Snowflake [CREATE DYNAMIC TABLE](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table) documentation.
571+
572+
To create a Dynamic Table, you can use the SQLAlchemy Core syntax as follows:
573+
574+
```python
575+
dynamic_test_table_1 = DynamicTable(
576+
"dynamic_MyUser",
577+
metadata,
578+
Column("id", Integer),
579+
Column("name", String),
580+
target_lag=(1, TimeUnit.HOURS), # Additionally, you can use SnowflakeKeyword.DOWNSTREAM
581+
warehouse='test_wh',
582+
refresh_mode=SnowflakeKeyword.FULL,
583+
as_query="SELECT id, name from MyUser;"
584+
)
585+
```
586+
587+
Alternatively, you can define a table without columns using the SQLAlchemy `select()` construct:
588+
589+
```python
590+
dynamic_test_table_1 = DynamicTable(
591+
"dynamic_MyUser",
592+
metadata,
593+
target_lag=(1, TimeUnit.HOURS),
594+
warehouse='test_wh',
595+
refresh_mode=SnowflakeKeyword.FULL,
596+
as_query=select(MyUser.id, MyUser.name)
597+
)
598+
```
599+
600+
### Notes
601+
602+
- Defining a primary key in a Dynamic Table is not supported, meaning declarative tables don’t support Dynamic Tables.
603+
- When using the `as_query` parameter with a string, you must explicitly define the columns. However, if you use the SQLAlchemy `select()` construct, you don’t need to explicitly define the columns.
604+
- Direct data insertion into Dynamic Tables is not supported.
605+
606+
464607
## Support
465608

466609
Feel free to file an issue or submit a PR here for general cases. For official support, contact Snowflake support at:

0 commit comments

Comments
 (0)