# Databases

Pydantic serves as a great tool for defining models for ORM (object relational mapping) libraries.
ORMs are used to map objects to database tables, and vice versa.

## SQLAlchemy

Pydantic can pair with SQLAlchemy, as it can be used to define the schema of the database models.

:::callout{intent="warning" title="Code Duplication"}
If you use Pydantic with SQLAlchemy, you might experience some frustration with code duplication.
If you find yourself experiencing this difficulty, you might also consider [`SQLModel`](https://sqlmodel.tiangolo.com/) which integrates Pydantic with SQLAlchemy such that much of the code duplication is eliminated.
:::

If you'd prefer to use pure Pydantic with SQLAlchemy, we recommend using Pydantic models alongside of SQLAlchemy models
as shown in the example below. In this case, we take advantage of Pydantic's aliases feature to name a `Column` after a reserved SQLAlchemy field, thus avoiding conflicts.

```python
import sqlalchemy as sa
from sqlalchemy.orm import declarative_base

from pydantic import BaseModel, ConfigDict, Field


class MyModel(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    metadata: dict[str, str] = Field(alias='metadata_')


Base = declarative_base()


class MyTableModel(Base):
    __tablename__ = 'my_table'
    id = sa.Column('id', sa.Integer, primary_key=True)
    # 'metadata' is reserved by SQLAlchemy, hence the '_'
    metadata_ = sa.Column('metadata', sa.JSON)


sql_model = MyTableModel(metadata_={'key': 'val'}, id=1)
pydantic_model = MyModel.model_validate(sql_model)

print(pydantic_model.model_dump())
#> {'metadata': {'key': 'val'}}
print(pydantic_model.model_dump(by_alias=True))
#> {'metadata_': {'key': 'val'}}
```

:::callout{intent="note"}
The example above works because aliases have priority over field names for
field population. Accessing `SQLModel`'s `metadata` attribute would lead to a `ValidationError`.
:::

Validating ORM objects can surface a less obvious class of failure: rows written before a constraint
was added, or columns that allow `NULL` where your model doesn't. These only fail when the offending
row is actually read, which may be long after a deploy, and
[recording failed validations](/guides/error-messages-troubleshooting) retains their structured errors and
rejected values, which can help identify the offending data.

## Related pages

- [API Documentation](./api-documentation-index.md)
- [Concepts](./concepts-index.md)
- [Dev Tools](./dev-tools-index.md)
- [Error Messages](./error-messages-index.md)
- [Examples](./examples-index.md)
- [Integrations](./integrations-index.md)
- [Internals](./internals-index.md)
- [Production Tools](./production-tools-index.md)
- [Pydantic](./pydantic-index.md)
- [Pydantic Core](./pydantic-core-index.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
