# Database Structure SilverStripe is currently hard-coded to use a fix mapping between data-objects and the underlying database structure - opting for "convention over configuration". This page details what that database structure is. ## Base tables Each direct sub-class of `[api:DataObject]` will have its own table. The following fields are always created. * ID: Primary Key * ClassName: An enumeration listing this data-class and all of its subclasses. * Created: A date/time field set to the creation date of this record * LastEdited: A date/time field set to the date this record was last edited Every object of this class **or any of its subclasses** will have an entry in this table ### Extra Fields * Every field listed in the data object's **$db** array will be included in this table. * For every relationship listed in the data object's **$has_one** array, there will be an integer field included in the table. This will contain the ID of the data-object being linked to. The database field name will be of the form "(relationship-name)ID", for example, ParentID. For polymorphic has_one relationships, there is an additional "(relationship-name)Class" field to identify the class this ID corresponds to. See [datamodel](/topics/datamodel#has_one). ### ID Generation When a new record is created, we don't use the database's built-in auto-numbering system. Instead, we generate a new ID by adding 1 to the current maximum ID. ## Subclass tables At SilverStripe's heart is an object-relational model. And a component of object-oriented data is **inheritance**. Unfortunately, there is no native way of representing inheritance in a relational database. What we do is store the data sub-classed objects across **multiple tables**. For example, suppose we have the following set of classes: * Class `[api:SiteTree]` extends `[api:DataObject]`: Title, Content fields * Class `[api:Page]` extends `[api:SiteTree]`: Abstract field * Class NewsSection extends `[api:SiteTree]`: *No special fields* * Class NewsArticle extend `[api:Page]`: ArticleDate field The data for the following classes would be stored across the following tables: * `[api:SiteTree]` * ID: Int * ClassName: Enum('SiteTree', 'Page', 'NewsArticle') * Created: Datetime * LastEdited: Datetime * Title: Varchar * Content: Text * `[api:Page]` * ID: Int * Abstract: Text * NewsArticle * ID: Int * ArticleDate: Date The way it works is this: * "Base classes" are direct sub-classes of `[api:DataObject]`. They are always given a table, whether or not they have special fields. This is called the "base table" * The base table's ClassName field is set to class of the given record. It's an enumeration of all possible sub-classes of the base class (including the base class itself) * Each sub-class of the base object will also be given its own table, *as long as it has custom fields*. In the example above, NewsSection didn't have its own data and so an extra table would be redundant. * In all the tables, ID is the primary key. A matching ID number is used for all parts of a particular record: record #2 in Page refers to the same object as record #2 in `[api:SiteTree]`. To retrieve a news article, SilverStripe joins the `[api:SiteTree]`, `[api:Page]` and NewsArticle tables by their ID fields. We use a left-join for robustness; if there is no matching record in Page, we can return a record with a blank Article field. ## Staging and versioning [todo] ## Schema auto-generation SilverStripe has a powerful tool for automatically building database schemas. We've designed it so that you should never have to build them manually. To access it, visit http://localhost/dev/build?flush=1. This script will analyze the existing schema, compare it to what's required by your data classes, and alter the schema as required. Put the ?flush=1 on the end if you've added PHP files, so that the rest of the system will find these new classes. It will perform the following changes: * Create any missing tables * Create any missing fields * Create any missing indexes * Alter the field type of any existing fields * Rename any obsolete tables that it previously created to _obsolete_(tablename) It **won't** do any of the following * Deleting tables * Deleting fields * Rename any tables that it doesn't recognize - so other applications can co-exist in the same database, as long as their table names don't match a SilverStripe data class. ## Related code The information documented in this page is reflected in a few places in the code: * `[api:DataObject]` * requireTable() is responsible for specifying the required database schema * instance_get() and instance_get_one() are responsible for generating the database queries for selecting data. * write() is responsible for generating the database queries for writing data. * `[api:Versioned]` * augmentWrite() is responsible for altering the normal database writing operation to handle versions. * augmentQuery() is responsible for altering the normal data selection queries to support versions. * augmentDatabase() is responsible for specifying the altered database schema to support versions. * `[api:MySQLDatabase]`: handles the mechanics of updating the database to have the required schema.