You start by declaring models. In Prisma you write a schema file; in SQLAlchemy or Django you write Python classes; in Drizzle you write TypeScript objects that describe each table and column. The ORM uses this definition both to validate your code and to know how to build queries.
When you call something like db.query.users.findMany({ where: { active: true } }), the ORM builds an abstract query, compiles it to a SQL string with bound parameters, and sends it through a connection from a pool. Parameters are bound separately from the SQL text, which is why ORMs give you protection against SQL injection almost for free.
Many heavier ORMs (Hibernate, SQLAlchemy, ActiveRecord) also track loaded objects in a session or identity map, batch changes, and flush them as a transaction when you commit. Lighter query builders like Drizzle skip most of that and stay close to the SQL you would have written, trading magic for predictability.
Most ORMs also ship migrations. You change a model, generate a migration file that holds the ALTER TABLE statements, and run it to evolve the schema in a versioned, repeatable way across dev, staging, and production.