Database columns generated from TCA
TYPO3 builds the expected database schema automatically from the TCA definitions.
Technical fields mentioned in the Table properties (ctrl) are created automatically.
Field definitions (columns) of most field types also create their database schema automatically.
If you have to override the default SQL types you can define them in the
ext_tables.sql.
For field types that are not supported, a definition in
ext_tables.sql is mandatory.
Table of contents
Overriding database schema in ext_tables.sql
A column defined in ext_tables.sql is never overwritten. Define a
column there to change its SQL type, its length, or its default.
Most tables need no column definition at all. The
CREATE TABLE
statement can stay empty, or you can leave it out:
CREATE TABLE tx_myextension_conference (
);
The missing columns are created in
System > Maintenance > Analyze Database Structure and by the
command
typo3 extension:.
Columns created from the ctrl section
Settings like enablecolumns, languageField, or sortby name a technical field. That field is created automatically.
The uid and pid columns are created automatically as well, together
with the indexes of a language-aware table and the t3ver_* columns of a
workspace-aware table.
Auto-generated structure
in TYPO3 Explained lists all ctrl settings that create a column.
Note
A ctrl setting also creates the TCA columns entry that belongs to
it. That is a different mechanism with a rule of its own. See
Auto-created columns from 'ctrl'.
Columns created from the column types
Each entry below gives the column as it is created on MySQL and MariaDB, followed by the Doctrine DBAL type it is declared with. PostgreSQL and SQLite get a column of that same Doctrine type, written in their own way.
The types none, passthrough, and user create no column. Define a
field of those types in ext_tables.sql.
nullable changes most of these columns: they lose their NOT NULL and
their default becomes NULL, for example
varchar instead of
varchar.
category-
int unsigned DEFAULT 0 NOT NULL, Doctrine typeinteger. The column counts the related records.With relationship set to
oneit is aTo Many longtext DEFAULT NULL, Doctrine typetext, with the list of uids. checksmallint unsigned DEFAULT 0 NOT NULL, Doctrine typesmallint. The TCAdefaultbecomes the default of the column.color-
varchar, Doctrine type(7) DEFAULT '' NOT NULL string, long enough for a value like#ff8700.With opacity enabled it is a
varchar, which also holds the alpha value.(9) countryvarchar, Doctrine type(16) DEFAULT NULL string. The field stores an ISO 3166-1 alpha-2 code likeDE. The remaining length is for items added by anitems.Proc Func datetime-
bigint DEFAULT 0 NOT NULL, Doctrine typebigint, holding a UNIX timestamp. The column is signed and covers dates before 1970 and after 2038.With dbType the column gets the native type of that name:
date,datetime, ortime. emailvarchar, Doctrine type(255) DEFAULT '' NOT NULL string.fileint unsigned DEFAULT 0 NOT NULL, Doctrine typeinteger. The column counts the file references. The references themselves are stored insys_.file_ reference flexlongtext DEFAULT NULL, Doctrine typetext, holding the XML of the FlexForm.folderlongtext DEFAULT NULL, Doctrine typetext.group-
longtext DEFAULT NULL, Doctrine typetext, with the list of references.With MM the column counts the related records instead:
int unsigned DEFAULT 0 NOT NULL, Doctrine typeinteger. imageManipulation longtext DEFAULT NULL, Doctrine typetext.inline-
int unsigned DEFAULT 0 NOT NULL, Doctrine typeinteger. The column counts the children. This applies to every relation withforeign_orfield MM.A relation that keeps the uids in the parent gets a
varcharwith a comma-separated list, Doctrine type(255) DEFAULT '' NOT NULL string.The child table gets columns too.
foreign_becomes anfield int unsigned DEFAULT 0 NOT NULL,foreign_atable_ field varchar. Both are created only if the TCA of the child does not define the field, or defines it as(255) DEFAULT '' NOT NULL passthrough. inputvarchar, Doctrine type(255) DEFAULT '' NOT NULL string. A max of its own becomes the length, for examplevarchar. Above 255 the column is a(40) text DEFAULT '' NOT NULLinstead, Doctrine typetext.jsonjson DEFAULT NULL, Doctrine typejson.languageint DEFAULT 0 NOT NULL, Doctrine typeinteger. The column is signed because-1stands for "all languages".linktext DEFAULT '' NOT NULL, Doctrine typetext.number-
int DEFAULT 0 NOT NULL, Doctrine typeinteger. The column is unsigned if range has alowerof0or higher.A scale above
0gives adecimal, Doctrine typedecimal. It has eight digits in front of the decimal point plus the scale: a scale of2givesdecimal, a scale of(10,2) DEFAULT 0 NOT NULL 6givesdecimal. SQLite stores such a value as a string so that it is not rounded.(14,6) passwordvarchar, Doctrine type(255) DEFAULT '' NOT NULL string.radio-
varchar, Doctrine type(255) DEFAULT '' NOT NULL string.If the values of
itemsare all integers the column is asmallint DEFAULT 0 NOT NULL, Doctrine typesmallint. Values outside-32768to32767give anint DEFAULT 0 NOT NULL, Doctrine typeinteger. select-
varchar, Doctrine type(255) DEFAULT '' string, with a comma-separated list of the selected values. A dbFieldLength of its own replaces the length of 255.A field that stores a single value, which is the
renderType selector aSingle maxitemsof1, gets anint DEFAULT 0 NOT NULLfor integer values and avarcharfor other values. The column is unsigned if no value is negative. It allows(255) DEFAULT '' NOT NULL NULLif an item has the valuenull.With
MMthe column counts the related records:int unsigned DEFAULT 0 NOT NULL, Doctrine typeinteger.In all other cases the column is a
longtext DEFAULT NULL, Doctrine typetext. slugtext DEFAULT NULL, Doctrine typetext.textlongtext DEFAULT NULL, Doctrine typetext.uuidchar, Doctrine type(36) NOT NULL guid. A UUID in its usual notation has 36 characters.
The intermediate table of an MM relation
A MM setting on a
field of the type category, group, inline, or select also creates
the intermediate table. That table has no TCA and no
ext_tables.sql entry of its own.
Auto creation of intermediate MM tables from TCA
describes when it is created and what it is for.
Its columns are:
uid_andlocal uid_foreign int unsigned DEFAULT 0 NOT NULL. The first points at the record that holds the field, the second at the related record.uid_always gets an index.foreign uid_gets one only together with thelocal uidcolumn below, because the primary key otherwise starts withuid_and indexes it already.local sortingandsorting_foreign int unsigned DEFAULT 0 NOT NULL, the order of the records on each side of the relation. Both are always created.tablenamesvarchar. A(64) DEFAULT '' NOT NULL groupfield with prepend_tname gets this column, and so do the two cases below.fieldnamevarchar. It is created together with(64) DEFAULT '' NOT NULL tablenamesif one intermediate table serves several fields: with MM_oppositeUsage, and for agroupfield whose allowed names more than one table or is*.uidint unsigned AUTO_, created only with multiple. That setting lets the same record take part in the relation twice, which the usual primary key forbids.INCREMENT NOT NULL
The primary key is uid_ and uid_, extended by tablenames
and fieldname if both exist. With multiple the uid column is the
primary key instead.
What to watch out for
A ctrl setting in an override file creates nothing
A setting that creates a column is read from the base file
Configuration/ only. The same setting in
Configuration/ comes too late and leaves you without
the column. See
Load order when building TCA.
An old definition keeps its old column
A column defined in ext_tables.sql stays as it is defined. An
extension written before TYPO3 created these columns therefore keeps every
column it defined, also those that no longer match. Delete the definition
to get the automatic column. Read the statements of
System > Maintenance > Analyze Database Structure before you
apply them: a change from one type to another can cut values short.
A changed TCA type changes the column
The automatic column follows the TCA. A select field that stored integer
values and now stores strings turns from an
int
into a
varchar
. The database converts the stored values, not TYPO3. Check
what that conversion does to the existing rows before you apply it.