The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →You can write SQL by hand in Python without giving up parameter safety or SQLAlchemy’s connection and result handling. In SQLAlchemy 2.x, use text() with Connection.execute() for most handwritten statements, and pass values separately as bound parameters. Use exec_driver_sql() only when you specifically need to send driver-level SQL; use Core expressions or ORM queries when their higher-level construction fits the job.
Run handwritten SQL with SQLAlchemy 2.x
This example uses SQLAlchemy’s documented textual SQL interface. The statement contains a named parameter, while the value is supplied separately to execute():
from sqlalchemy import create_engine, text
engine = create_engine("sqlite:///app.db")
with engine.connect() as conn:
result = conn.execute(
text("SELECT x, y FROM some_table WHERE y > :y"),
{"y": 2},
)
for row in result.mappings():
print(row["x"], row["y"])
The connection context manager closes the connection when the block ends. text() makes the SQL string a SQLAlchemy textual statement, and result.mappings() lets you access returned rows by column name. The example follows the SQLAlchemy 2.0 tutorial.
Do not put quotes around :y or build a query string containing the value yourself. The SQLAlchemy dialect and database driver handle binding the separate value using the conventions appropriate to that backend.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
Keep values separate from SQL
Never insert untrusted values into SQL with an f-string, concatenation, percent formatting, or another interpolation method. For example, do not form a statement such as f"... WHERE name = '{name}'". Pass the value through the API’s parameter mechanism instead:
stmt = text("SELECT id FROM users WHERE name = :name")
with engine.connect() as conn:
result = conn.execute(stmt, {"name": name})
SQLAlchemy’s textual SQL guidance says not to stringify Python values into statements and advises: “Always use bound parameters.” The SQLAlchemy FAQ likewise recommends bound parameters for programmatically executed non-DDL statements. Binding is a safety rule for values; it does not turn arbitrary SQL structure into safe input.
Values are not identifiers or SQL fragments
A parameter represents a value, such as a name or numeric threshold. It does not stand in for a table name, column name, sort direction, or arbitrary SQL syntax. If those parts must vary, select them from a deliberate allowlist or use an identifier-composition facility supported by the specific backend or library. Do not treat a bound-value placeholder as a general-purpose way to inject SQL structure.
Choose between text(), driver SQL, and expressions
| Approach | SQL control | SQLAlchemy integration | Driver dependence | Best fit |
|---|---|---|---|---|
text() with Connection.execute() |
You write the SQL statement directly. | Uses SQLAlchemy’s textual statement and parameter handling, with SQLAlchemy-level typing and result behavior. | Dialect translates parameter handling for the configured backend. | Handwritten SQL that should remain integrated with SQLAlchemy. |
Connection.exec_driver_sql() |
You pass a SQL string directly to the underlying DBAPI driver. | Bypasses SQLAlchemy’s text() statement abstraction; execution follows driver-level conventions. |
More directly dependent on the DBAPI driver, including its parameter style. | Cases that specifically require driver-direct SQL behavior. |
| Core expressions or ORM queries | You construct the query from SQLAlchemy expression or ORM constructs rather than writing the whole statement as text. | Provides a higher level of query construction; ORM statements use the mapped model. | SQLAlchemy handles dialect translation for the configured backend. | Queries built programmatically or work that benefits from expression and ORM abstractions. |
SQLAlchemy describes textual SQL as an exception in ordinary day-to-day use, not as an unsupported feature. Core and ORM constructs provide more abstraction; they are useful when query composition and mapped entities matter. The Core overview and ORM Querying Guide document those alternatives.
When text() is the practical default
Choose text() when the statement is clearest as SQL you write yourself but you still want SQLAlchemy’s parameter and result integration. This is often a straightforward fit for a fixed query with a few variable values.
When exec_driver_sql() is warranted
Choose exec_driver_sql() only when the statement needs to go straight to the DBAPI driver. Unlike text(), its SQL string and parameter conventions are driver-specific. Consult the configured driver’s documentation for its placeholder style and calling conventions. The distinction is described in SQLAlchemy’s Engines and Connections documentation.
Rank #4
When Core or the ORM is a better fit
When application logic assembles a query from optional conditions or other changing pieces, Core expressions can provide structured construction. For ORM queries in SQLAlchemy 2.x, build a select() statement and execute it with Session.execute(). Handwritten SQL and ORM querying are neighboring options within SQLAlchemy, not mutually exclusive camps.
Account for the database and driver
SQLAlchemy supports dialects for several major database families, but using a dialect also requires an appropriate DB-API implementation. The example above explicitly targets SQLite with the sqlite:///app.db connection URL; it does not imply that every backend uses the same SQL placeholder syntax or driver behavior. With text(), use SQLAlchemy’s named parameter form in the statement and provide a separate mapping of values. With exec_driver_sql(), follow the underlying driver’s own parameter convention. SQLAlchemy lists supported dialect families and the DB-API requirement on its Features page.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
Do not inline values for execution or debugging
SQLAlchemy’s literal_binds option can render values inline in some SQL output, but it is not a substitute for binding values during execution. The FAQ presents inline rendering mainly as a logging or debugging aid and notes datatype limitations; it warns against using it with untrusted input. Keep execution parameters separate rather than converting them into SQL text.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




