What is TEXTIMAGE_ON [PRIMARY]?

I worked on many tables and all had this thing:

CREATE TABLE Persons(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [modified_on] [datetime] NULL,
    [modified_by] [varchar](200) NULL,
) 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

What is TEXTIMAGE_ON [PRIMARY] in SQL Server/Transact-SQL?


Given that the format is:

CREATE TABLE TableName(...) TEXTIMAGE_ON { filegroup | "default" }

TEXTIMAGE refers to all big/unlimited-size field types: text, ntext, image, xml, varchar(max), nvarchar(max), varbinary(max), and CLR user-defined type columns (including geometry and geography).

Then, you need to know what Files and FileGroups are. From the MSDN entry on Database Files and Filegroups:

File

At a minimum, every SQL Server database has two operating system files: a data file and a log file. Data files contain data and objects such as tables, indexes, stored procedures, and views. Log files contain the information that is required to recover all transactions in the database. Data files can be grouped together in filegroups for allocation and administration purposes.

Filegroups

Every database has a primary filegroup. This filegroup contains the primary data file and any secondary files that are not put into other filegroups. User-defined filegroups can be created to group data files together for administrative, data allocation, and placement purposes.

So,

CREATE TABLE ... ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Would appear to be somewhat redundant, as it is saying that the mentioned large-text-value columns should be stored within the primary filegroup, which is actually the default action.

Assuming the existence of a custom filegroup called CUSTOM, you would probably write something like this:

CREATE TABLE ... ON [PRIMARY] TEXTIMAGE_ON [CUSTOM]

You would create a custom filegroup to store large binary or text, and in this case the 'normal' fields info would sit in a data file in the primary filegroup, while the associated 'large' fields would be stored in a physically distinct data file (in the secondary custom filegroup).

You would do this so that you could separate the core relational datamodel (which would presumably be relatively small in terms of disk space) from the large fields (which will require proportionally more disk space) - in order to allow distinct archiving or replication strategies to be applied to each filegroup.


From the MSDN

TEXTIMAGE_ON { filegroup | "default" }

Indicates that the text, ntext, image, xml, varchar(max), nvarchar(max), varbinary(max), and CLR user-defined type columns (including geometry and geography) are stored on the specified filegroup.

TEXTIMAGE_ON is not allowed if there are no large value columns in the table. TEXTIMAGE_ON cannot be specified if <partition_scheme> is specified. If "default" is specified, or if TEXTIMAGE_ON is not specified at all, the large value columns are stored in the default filegroup. The storage of any large value column data specified in CREATE TABLE cannot be subsequently altered.

NOTE: In this context, default is not a keyword. It is an identifier for the default filegroup and must be delimited, as in TEXTIMAGE_ON "default" or TEXTIMAGE_ON [default]. If "default" is specified, the QUOTED_IDENTIFIER option must be ON for the current session. This is the default setting.


If you dont have any large text columns i.e. text, ntext, image, xml, varchar(max), nvarchar(max), varbinary(max), and CLR then you can just use:

CREATE TABLE Persons(
[id] [int] IDENTITY(1,1) NOT NULL,
[modified_on] [datetime] NULL,
[modified_by] [varchar](200) NULL,)ON [PRIMARY]