1. Interview Questions -SQLAlchemy ORM

source:

https://docs.sqlalchemy.org/en/20/orm/index.htmlarrow-up-right

1. What is the purpose of DeclarativeBase in SQLAlchemy ORM?

Answer: DeclarativeBase is a base class from which all ORM models inherit. It provides the foundational mapping capability to link Python classes with database tables.


2. How do you define a table name in an ORM model?

Answer: Use the __tablename__ attribute in the model class to define the table name.

class User(Base):
    __tablename__ = "user_account"

3. What import is required to define mapped columns in ORM models?

Answer: You should import Mapped and mapped_column from sqlalchemy.orm.

from sqlalchemy.orm import Mapped, mapped_column

4. How do you define a primary key column in a model?

Answer: Use mapped_column(primary_key=True) to mark the column as a primary key.

id: Mapped[int] = mapped_column(primary_key=True)

5. How can you define a column with a specific string length?

Answer: Use mapped_column(String(length)).


6. What is the advantage of using Mapped over plain type annotations in SQLAlchemy 2.0?

Answer: Mapped provides type checking and helps SQLAlchemy understand that the field is part of the ORM mapping.


7. How do you declare a relationship between two models?

Answer: Use the relationship() function within the model.


8. What is back_populates used for in relationships?

Answer: It sets up a bidirectional relationship by linking two related fields from different models.


9. How do you represent a foreign key in an ORM model?

Answer: Use mapped_column(ForeignKey("table.column")).


10. How do you define a string column with no length limit?

Answer: Simply use Text or String without specifying a length.


11. How do you create the tables defined by ORM models in the database?

Answer: Call Base.metadata.create_all(engine).


12. What does metadata.create_all() do?

Answer: It generates the SQL schema (CREATE TABLE statements) based on the ORM models.


13. How do you configure the base class to use a metadata object?

Answer: By inheriting from DeclarativeBase, which already includes metadata.


14. What is the purpose of Mapped[List[...]] in relationship fields?

Answer: It indicates a one-to-many relationship, where the current model owns a list of related models.


15. Can you use forward declarations for models in relationships?

Answer: Yes, by quoting the class name as a string, e.g., "Address".


16. How does SQLAlchemy map columns to class attributes?

Answer: By using Mapped annotations and mapped_column definitions inside a model class.


17. Is the use of __init__ required when defining ORM models?

Answer: No, SQLAlchemy can automatically generate the constructor based on the fields.


18. What is the role of Base.metadata?

Answer: It holds all the schema-level objects like tables and constraints and is used to emit schema DDL.


19. How do you specify a nullable column?

Answer: By setting nullable=True (default), or nullable=False for non-nullable.


20. How do relationships handle collections by default?

Answer: By default, a relationship with List[...] maps to a Python list of related objects.


Here’s another set of 20 SQLAlchemy ORM interview questions and answers, continuing from the same SQLAlchemy ORM Quickstart v2.0arrow-up-right page, focused more on deeper and nuanced concepts:


21. What does ForeignKey("user_account.id") refer to in a mapped column?

Answer: It specifies that the column is a foreign key referencing the id column of the user_account table.


22. Can a model have multiple foreign keys?

Answer: Yes, a model can have multiple foreign keys referencing one or more different tables.


23. How do you define a one-to-many relationship in SQLAlchemy?

Answer: Use relationship() in the parent model and a foreign key in the child model.


24. What happens if you omit back_populates in relationships?

Answer: The relationship will still work unidirectionally, but bidirectional updates and synchronization won’t happen automatically.


25. What’s the difference between backref and back_populates?

Answer: backref auto-creates the reverse relationship, while back_populates requires explicit declaration in both models.


26. What does the String(30) in a column mean?

Answer: It defines a column of type VARCHAR with a maximum length of 30 characters.


27. Can you define constraints like unique=True on columns?

Answer: Yes, mapped_column(..., unique=True) adds a uniqueness constraint to that column.


28. How do you define default values for columns in ORM models?

Answer: Use the default parameter in mapped_column.


29. How can you enforce non-null constraints in a model field?

Answer: Use nullable=False in the column definition.


30. What data types can you use in mapped_column?

Answer: Common ones include Integer, String, Text, Boolean, Date, DateTime, Float, etc.


31. What does Mapped[int] indicate to SQLAlchemy?

Answer: It tells SQLAlchemy that the attribute is a mapped column of type int.


32. How are Python classes linked to SQL tables in SQLAlchemy ORM?

Answer: By inheriting from a base class (Base) and using __tablename__ along with column mappings.


33. What would happen if two models used the same __tablename__?

Answer: A conflict would occur during metadata creation, likely resulting in an error.


34. Can you mix traditional SQLAlchemy Core with ORM?

Answer: Yes, SQLAlchemy allows mixing ORM and Core features in the same application.


35. How does SQLAlchemy handle pluralization or table name inference?

Answer: It does not infer table names — you must explicitly set __tablename__.


36. What is the default collection type for relationships in SQLAlchemy ORM?

Answer: Python list.


37. What is the purpose of the DeclarativeBase metaclass?

Answer: It tracks all models and generates metadata used to emit DDL statements like CREATE TABLE.


38. Can you extend multiple base classes for models in SQLAlchemy ORM?

Answer: No, models should inherit from a single declarative base to avoid conflicts.


39. Why are string-based annotations (e.g., "Address") used in relationships?

Answer: To enable forward references when the related class has not yet been defined.


40. What does Base.metadata.create_all(engine) actually use to build the schema?

Answer: It uses the __table__ definitions attached to each model and executes the appropriate SQL via the provided engine.


41. Can you define a composite primary key using DeclarativeBase?

Answer: Yes, by using multiple mapped_column(..., primary_key=True) in the model.


42. How do you map a class without defining __tablename__?

Answer: You must define __tablename__; otherwise, the class won't map to a table, and SQLAlchemy will raise an error during metadata creation.


43. What happens if Mapped is not used in column type hints?

Answer: SQLAlchemy will not treat the attribute as part of the ORM mapping; it will be ignored.


44. How can you access all defined tables in your ORM setup?

Answer: Use Base.metadata.tables, which returns a dictionary of all mapped table names and their Table objects.


45. Is it necessary to use relationship() on both sides of a relation?

Answer: No, but it is highly recommended if you need bidirectional navigation and synchronization.


46. How do you handle circular imports in relationship declarations?

Answer: Use a string (e.g., "User") to declare the related class in relationship() to avoid direct reference.


47. Can Mapped be used with generic types like Optional or List?

Answer: Yes, such as Mapped[Optional[str]] or Mapped[List["ModelName"]].


48. How do you avoid automatic pluralization of relationships?

Answer: SQLAlchemy does not auto-pluralize by default. You control naming manually.


49. What does the __init__ method do in SQLAlchemy ORM models?

Answer: If not explicitly defined, SQLAlchemy auto-generates __init__ to accept mapped columns as keyword arguments.


50. How do you associate a model with an existing table that was already created in the DB?

Answer: Use __table__ = Table(...) instead of __tablename__, and map the existing table via reflection or manual table definition.


Last updated