CREATE TABLE (Transact-SQL)

更新日期: 2006 年 12 月 12 日

创建新表。

主题链接图标Transact-SQL 语法约定

语法

CREATE TABLE 
    [ database_name . [ schema_name ] . | schema_name . ] table_name 
        ( { <column_definition> | <computed_column_definition> }
        [ <table_constraint> ] [ ,...n ] ) 
    [ ON { partition_scheme_name ( partition_column_name ) | filegroup 
        | "default" } ] 
    [ { TEXTIMAGE_ON { filegroup | "default" } ] 
[ ; ]

<column_definition> ::=
column_name <data_type>
    [ COLLATE collation_name ] 
    [ NULL | NOT NULL ]
    [ 
        [ CONSTRAINT constraint_name ] DEFAULT constant_expression ] 
      | [ IDENTITY [ ( seed , increment ) ] [ NOT FOR REPLICATION ] 
    ]
    [ ROWGUIDCOL ] [ <column_constraint> [ ...n ] ] 

<data type> ::= 
[ type_schema_name . ] type_name 
    [ ( precision [ , scale ] | max | 
        [ { CONTENT | DOCUMENT } ] xml_schema_collection ) ] 

<column_constraint> ::= 
[ CONSTRAINT constraint_name ] 
{     { PRIMARY KEY | UNIQUE } 
        [ CLUSTERED | NONCLUSTERED ] 
        [ 
            WITH FILLFACTOR = fillfactor  
          | WITH ( < index_option > [ , ...n ] ) 

        ]
        [ ON { partition_scheme_name ( partition_column_name ) 
            | filegroup | "default" } ]
  | [ FOREIGN KEY ] 
        REFERENCES [ schema_name . ] referenced_table_name [ ( ref_column ) ] 
        [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 
        [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 
        [ NOT FOR REPLICATION ] 
  | CHECK [ NOT FOR REPLICATION ] ( logical_expression ) 
} 

<computed_column_definition> ::=
column_name AS computed_column_expression 
[ PERSISTED [ NOT NULL ] ]
[ 
    [ CONSTRAINT constraint_name ]
    { PRIMARY KEY | UNIQUE }
        [ CLUSTERED | NONCLUSTERED ]
        [ 
            WITH FILLFACTOR = fillfactor 
          | WITH ( <index_option> [ , ...n ] )
        ]
        [ ON { partition_scheme_name ( partition_column_name ) 
            | filegroup | "default" } ]
    | [ FOREIGN KEY ] 
        REFERENCES referenced_table_name [ ( ref_column ) ] 
        [ ON DELETE { NO ACTION | CASCADE } ] 
        [ ON UPDATE { NO ACTION } ] 
        [ NOT FOR REPLICATION ] 
    | CHECK [ NOT FOR REPLICATION ] ( logical_expression ) 
] 

< table_constraint > ::=
[ CONSTRAINT constraint_name ] 
{ 
    { PRIMARY KEY | UNIQUE } 
        [ CLUSTERED | NONCLUSTERED ] 

                (column [ ASC | DESC ] [ ,...n ] ) 
        [ 
            WITH FILLFACTOR = fillfactor 
           |WITH ( <index_option> [ , ...n ] ) 
        ]
        [ ON { partition_scheme_name (partition_column_name)
            | filegroup | "default" } ] 
    | FOREIGN KEY 
                ( column [ ,...n ] ) 
        REFERENCES referenced_table_name [ ( ref_column [ ,...n ] ) ] 
        [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 
        [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] 
        [ NOT FOR REPLICATION ] 
    | CHECK [ NOT FOR REPLICATION ] ( logical_expression ) 
} 

<index_option> ::=
{ 
    PAD_INDEX = { ON | OFF } 
  | FILLFACTOR = fillfactor 
  | IGNORE_DUP_KEY = { ON | OFF } 
  | STATISTICS_NORECOMPUTE = { ON | OFF } 
  | ALLOW_ROW_LOCKS = { ON | OFF} 
  | ALLOW_PAGE_LOCKS ={ ON | OFF} 
}

参数

  • database_name
    在其中创建表的数据库的名称。database_name 必须指定现有数据库的名称。如果未指定,则 database_name 默认为当前数据库。当前连接的登录名必须与 database_name 所指定数据库中的一个现有用户 ID 关联,并且该用户 ID 必须具有 CREATE TABLE 权限。
  • schema_name
    新表所属架构的名称。
  • table_name
    新表的名称。表名必须遵循标识符规则。除了本地临时表名(以单个数字符号 (#) 为前缀的名称)不能超过 116 个字符外,table_name 最多可包含 128 个字符。
  • column_name
    表中列的名称。列名必须遵循标识符规则,并在表中唯一。column_name 可包含 1 至 128 个字符。对于使用 timestamp 数据类型创建的列,可以省略 column_name 。如果未指定 column_name,则 timestamp 列的名称将默认为 timestamp
  • computed_column_expression
    定义计算列的值的表达式。计算列并不是物理地存储在表中的虚拟列,除非此列标记为 PERSISTED。该列由同一表中的其他列通过表达式计算得到。例如,计算列可以定义为 cost AS price * qty。表达式可以是非计算列的列名、常量、函数、变量,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能是子查询,也不能包含别名数据类型。

    计算列可用于选择列表、WHERE 子句、ORDER BY 子句或任何可使用正则表达式的其他位置,但下列情况除外:

    • 计算列不能用作 DEFAULT 或 FOREIGN KEY 约束定义,也不能与 NOT NULL 约束定义一起使用。但是,如果计算列的值由具有确定性的表达式定义,并且索引列中允许计算结果的数据类型,则可将该列用作索引中的键列,或用作 PRIMARY KEY 或 UNIQUE 约束的一部分。
      例如,如果表中含有整数列 ab,则可以对计算列 a+b 创建索引,但不能对计算列 a+DATEPART(dd, GETDATE()) 创建索引,因为在以后的调用中,其值可能发生改变。
    • 计算列不能作为 INSERT 或 UPDATE 语句的目标。
    ms174979.note(zh-cn,SQL.90).gif注意:
    表中计算列所使用的列值因行而异,因此计算列的每一行可能有不同的值。

    计算列的为空性是由 SQL Server 2005 数据库引擎根据使用的表达式自动确定的。即使只有不可为空的列,大多数表达式的结果也认为是可为空的,因为可能的下溢或溢出也将生成 NULL 结果。使用带 AllowsNull 属性的 COLUMNPROPERTY 函数可查明表中任何计算列的为空性。通过与 check_expression 常量一起指定 ISNULL(其中,常量是替换所有 NULL 结果的非空值),可以将可为空的表达式转换为不可为空的表达式。对于基于公共语言运行时 (CLR) 用户定义类型表达式的计算列,需要对此类型有 REFERENCES 权限。

  • PERSISTED
    指定 SQL Server 数据库引擎将在表中物理存储计算值,而且,当计算列依赖的任何其他列发生更新时对这些计算值进行更新。将计算列标记为 PERSISTED,可允许您对具有确定性、但不精确的计算列创建索引。有关详细信息,请参阅为计算列创建索引。用作已分区表的分区依据列的所有计算列都必须显式标记为 PERSISTED。指定 PERSISTED 时,computed_column_expression 必须具有确定性。
  • ON { <partition_scheme> | filegroup | "default" }
    指定存储表的分区架构或文件组。如果指定了 <partition_scheme>,则该表将成为已分区表,其分区存储在 <partition_scheme> 所指定的一个或多个文件组的集合中。如果指定了 filegroup,则该表将存储在命名的文件组中。数据库中必须存在该文件组。如果指定了 "default",或者根本未指定 ON,则表存储在默认文件组中。CREATE TABLE 中指定的表的存储机制以后不能进行更改。

    ON {<partition_scheme> | filegroup | default} 也可在 PRIMARY KEY 约束或 UNIQUE 约束中指定。这些约束会创建索引。如果指定了 filegroup,则索引将存储在命名的文件组中。如果指定了 "default",或者根本未指定 ON,则索引将与表存储在同一文件组中。如果 PRIMARY KEY 约束或 UNIQUE 约束创建聚集索引,则表的数据页将与索引存储在同一文件组中。如果指定了 CLUSTERED 或约束另外创建了聚集索引,并且指定的 <partition_scheme> 不同于表定义的 <partition_scheme> 或 filegroup ,或反之,则只接受约束定义,而忽略其他定义。

    ms174979.note(zh-cn,SQL.90).gif注意:
    在此上下文中,default 不是关键字。它是默认文件组的标识符,并且必须进行分隔(类似于 ON "default" 或 ON[default])。如果指定了 "default",则当前会话的 QUOTED_IDENTIFIER 选项必须为 ON。这是默认设置。有关详细信息,请参阅 SET QUOTED_IDENTIFIER (Transact-SQL)
  • TEXTIMAGE_ON { filegroup| "default" }
    指示 textntextimagexmlvarchar(max)nvarchar(max)varbinary(max) 和 CLR 用户定义类型的列存储在指定文件组的关键字。

    如果表中没有较大值的列,则不允许使用 TEXTIMAGE_ON。如果指定了 <partition_scheme>,则不能指定 TEXTIMAGE_ON。如果指定了 "default",或者根本未指定 TEXTIMAGE_ON,则较大值的列存储在默认文件组中。CREATE TABLE 中指定的任何较大值列的数据存储以后都不能进行更改。

    ms174979.note(zh-cn,SQL.90).gif注意:
    在此上下文中,default 不是关键字。它是默认文件组的标识符,而且必须进行分隔,如 TEXTIMAGE_ON "default" 或 TEXTIMAGE_ON [default] 中所示。如果指定了 "default",则当前会话的 QUOTED_IDENTIFIER 选项必须为 ON。这是默认设置。有关详细信息,请参阅 SET QUOTED_IDENTIFIER (Transact-SQL)
  • [ type_schema_name**.** ] type_name
    指定列的数据类型以及该列所属的架构。数据类型可以是下列类型之一:

    • SQL Server 2005 系统数据类型。
    • 基于 SQL Server 系统数据类型的别名类型。必须先用 CREATE TYPE 语句创建别名数据类型,然后才能将其用于表定义中。在 CREATE TABLE 语句中,可以覆盖别名数据类型的 NULL 或 NOT NULL 赋值。但是,指定的长度不能更改;不能在 CREATE TABLE 语句中指定别名数据类型的长度。
    • CLR 用户定义类型。必须先用 CREATE TYPE 语句创建 CLR 用户定义类型,然后才能将其用于表定义中。若要创建 CLR 用户定义类型的列,则需要对此类型具有 REFERENCES 权限。

    如果未指定 type_schema_name,则 SQL Server 数据库引擎将按以下顺序引用 type_name

    • SQL Server 系统数据类型。
    • 当前数据库中当前用户的默认架构。
    • 当前数据库中的 dbo 架构。
  • max
    只适用于 varcharnvarcharvarbinary 数据类型,用于存储 2^31 个字节的字符和二进制数据,以及 2^30 个字节的 Unicode 数据。
  • CONTENT
    指定 column_name 中每个数据类型为 xml 的实例都可包含多个顶级元素。CONTENT 仅适用于 xml 数据类型,并且只有在同时指定了 xml_schema_collection 时才能指定 CONTENT。如果未指定,则 CONTENT 为默认行为。
  • DOCUMENT
    指定 column_name 中每个数据类型为 xml 的实例都只能包含一个顶级元素。DOCUMENT 仅适用于 xml 数据类型,并且只有同时指定了 xml_schema_collection 时才能指定 DOCUMENT。
  • xml_schema_collection
    仅适用于 xml 数据类型,用于将 XML 架构集合与该类型相关联。在架构中键入 xml 列之前,必须先使用 CREATE XML SCHEMA COLLECTION 在数据库中创建该架构。
  • DEFAULT
    如果在插入过程中未显式提供值,则指定为列提供的值。DEFAULT 定义可适用于除定义为 timestamp 或带 IDENTITY 属性的列以外的任何列。如果为用户定义类型列指定了默认值,则该类型应当支持从 constant_expression 到用户定义类型的隐式转换。删除表时,将删除 DEFAULT 定义。只有常量值(例如字符串)、标量函数(系统函数、用户定义函数或 CLR 函数)或 NULL 可用作默认值。为了与 SQL Server 的早期版本兼容,可以为 DEFAULT 分配约束名称。
  • constant_expression
    是用作列的默认值的常量、NULL 或系统函数。
  • IDENTITY
    指示新列是标识列。在表中添加新行时,数据库引擎将为该列提供一个唯一的增量值。标识列通常与 PRIMARY KEY 约束一起用作表的唯一行标识符。可以将 IDENTITY 属性分配给 tinyintsmallintintbigintdecimal(p,0)numeric(p,0) 列。每个表只能创建一个标识列。不能对标识列使用绑定默认值和 DEFAULT 约束。必须同时指定种子和增量,或者两者都不指定。如果二者都未指定,则取默认值 (1,1)。
  • seed
    是装入表的第一行所使用的值。
  • increment
    是向装载的前一行的标识值中添加的增量值。
  • NOT FOR REPLICATION
    在 CREATE TABLE 语句中,可为 IDENTITY 属性、FOREIGN KEY 约束和 CHECK 约束指定 NOT FOR REPLICATION 子句。如果为 IDENTITY 属性指定了该子句,则复制代理执行插入时,标识列中的值将不会增加。如果为约束指定了此子句,则当复制代理执行插入、更新或删除操作时,将不会强制执行此约束。有关详细信息,请参阅使用 NOT FOR REPLICATION 来控制约束、标识和触发器
  • ROWGUIDCOL
    指示新列是行 GUID 列。对于每个表,只能将其中的一个 uniqueidentifier 列指定为 ROWGUIDCOL 列。应用 ROWGUIDCOL 属性将使列能够使用 $ROWGUID 进行引用。ROWGUIDCOL 属性只能分配给 uniqueidentifier 列。如果数据库兼容级别小于或等于 65,则 ROWGUIDCOL 关键字无效。有关详细信息,请参阅 sp_dbcmptlevel (Transact-SQL)。用户定义数据类型列不能使用 ROWGUIDCOL 指定。

    ROWGUIDCOL 属性并不强制列中所存储值的唯一性。ROWGUIDCOL 也不会为插入表的新行自动生成值。若要为每列生成唯一值,请对 INSERT 语句使用 NEWIDNEWSEQUENTIALID 函数,或使用这些函数作为该列的默认值。

  • COLLATE collation_name
    指定列的排序规则。排序规则名称可以是 Windows 排序规则名称或 SQL 排序规则名称。collation_name 只适用于 charvarchartextncharnvarcharntext 等数据类型列。如果没有指定该参数,则该列的排序规则是用户定义数据类型的排序规则(如果列为用户定义数据类型)或数据库的默认排序规则。

    有关 Windows 和 SQL 排序规则名称的详细信息,请参阅 Windows 排序规则名称SQL 排序规则名称

    有关 COLLATE 子句的详细信息,请参阅 COLLATE (Transact-SQL)

  • CONSTRAINT
    可选关键字,表示 PRIMARY KEY、NOT NULL、UNIQUE、FOREIGN KEY 或 CHECK 约束定义的开始。有关详细信息,请参阅约束
  • constraint_name
    约束的名称。约束名称必须在表所属的架构中唯一。
  • NULL | NOT NULL
    确定列中是否允许使用空值。严格来讲,NULL 不是约束,但可以像指定 NOT NULL 那样指定它。只有同时指定了 PERSISTED 时,才能为计算列指定 NOT NULL。
  • PRIMARY KEY
    是通过唯一索引对给定的一列或多列强制实体完整性的约束。每个表只能创建一个 PRIMARY KEY 约束。
  • UNIQUE
    一个约束,该约束通过唯一索引为一个或多个指定列提供实体完整性。一个表可以有多个 UNIQUE 约束。
  • CLUSTERED | NONCLUSTERED
    指示为 PRIMARY KEY 或 UNIQUE 约束创建聚集索引还是非聚集索引。PRIMARY KEY 约束默认为 CLUSTERED,UNIQUE 约束默认为 NONCLUSTERED。

    在 CREATE TABLE 语句中,可只为一个约束指定 CLUSTERED。如果在为 UNIQUE 约束指定 CLUSTERED 的同时又指定了 PRIMARY KEY 约束,则 PRIMARY KEY 将默认为 NONCLUSTERED。

  • FOREIGN KEY REFERENCES
    为列中的数据提供引用完整性的约束。FOREIGN KEY 约束要求列中的每个值在所引用的表中对应的被引用列中都存在。FOREIGN KEY 约束只能引用在所引用的表中是 PRIMARY KEY 或 UNIQUE 约束的列,或所引用的表中在 UNIQUE INDEX 内的被引用列。计算列上的外键也必须标记为 PERSISTED。
  • [ schema_name**.****] referenced_table_name]
    是 FOREIGN KEY 约束引用的表的名称,以及该表所属架构的名称。
  • **(**ref_column [ ,... n ] )
    是 FOREIGN KEY 约束所引用的表中的一列或多列。
  • ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT }
    指定如果已创建表中的行具有引用关系,并且被引用行已从父表中删除,则对这些行采取的操作。默认值为 NO ACTION。

    • NO ACTION
      数据库引擎将引发错误,并回滚对父表中相应行的删除操作。
    • CASCADE
      如果从父表中删除一行,则将从引用表中删除相应行。
    • SET NULL
      如果父表中对应的行被删除,则组成外键的所有值都将设置为 NULL。若要执行此约束,外键列必须可为空值。
    • SET DEFAULT
      如果父表中对应的行被删除,则组成外键的所有值都将设置为默认值。若要执行此约束,所有外键列都必须有默认定义。如果某个列可为空值,并且未设置显式的默认值,则将使用 NULL 作为该列的隐式默认值。

    如果该表将包含在使用逻辑记录的合并发布中,则不要指定 CASCADE。有关逻辑记录的详细信息,请参阅通过逻辑记录对相关行的更改进行分组

    如果表中已存在 ON DELETE 的 INSTEAD OF 触发器,则不能定义 ON DELETE 的 CASCADE 操作。

    例如,在 AdventureWorks 数据库中,ProductVendor 表与 Vendor 表有引用关系。ProductVendor.VendorID 外键引用 Vendor.VendorID 主键。

    如果对 Vendor 表中的行执行 DELETE 语句,并且为 ProductVendor.VendorID 指定了 ON DELETE CASCADE 操作,则数据库引擎将检查 ProductVendor 表中是否有一个或多个依赖行。如果存在依赖行,则 ProductVendor 表中的依赖行将随 Vendor 表中的被引用行一同删除。

    相反,如果指定了 NO ACTION,并且 ProductVendor 表中至少有一行引用 Vendor 行,则数据库引擎将引发错误并回滚对 Vendor 行的删除操作。

  • ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT }
    指定在发生更改的表中,如果行有引用关系且引用的行在父表中被更新,则对这些行采取什么操作。默认值为 NO ACTION。

    • NO ACTION
      数据库引擎将引发错误,并回滚对父表中相应行的更新操作。
    • CASCADE
      如果在父表中更新了一行,则将在引用表中更新相应的行。
    • SET NULL
      如果更新了父表中的相应行,则会将构成外键的所有值设置为 NULL。若要执行此约束,外键列必须可为空值。
    • SET DEFAULT
      如果更新了父表中的相应行,则会将构成外键的所有值都设置为其默认值。若要执行此约束,所有外键列都必须有默认定义。如果某个列可为空值,并且未设置显式的默认值,则将使用 NULL 作为该列的隐式默认值。

    如果该表将包含在使用逻辑记录的合并发布中,则不要指定 CASCADE。有关逻辑记录的详细信息,请参阅通过逻辑记录对相关行的更改进行分组

    如果正在更改的表已经存在 INSTEAD OF 触发器 ON UPDATE,则不能定义 ON UPDATE CASCADE。

    例如,在 AdventureWorks 数据库中,ProductVendor 表和 Vendor 表之间具有如下引用关系:ProductVendor.VendorID 外键引用 Vendor.VendorID 主键。

    如果对 Vendor 表中的行执行 UPDATE 语句,并且为 ProductVendor.VendorID 指定了 ON UPDATE CASCADE 操作,则数据库引擎将检查 ProductVendor 表中的一个或多个依赖行。如果存在依赖行,则 ProductVendor 表中的依赖行将随 Vendor 表中的被引用行一同更新。

    反之,如果指定了 NO ACTION,并且 ProductVendor 表中至少有一行引用 Vendor 行,则数据库引擎将引发错误并回滚对 Vendor 行的更新操作。

  • CHECK
    一个约束,该约束通过限制可输入一列或多列中的可能值来强制实现域完整性。计算列上的 CHECK 约束也必须标记为 PERSISTED。
  • logical_expression
    返回 TRUE 或 FALSE 的逻辑表达式。别名数据类型不能作为表达式的一部分。
  • column
    用括号括起来的一列或多列,在表约束中表示这些列用在约束定义中。
  • [ ASC | DESC ]
    指定加入到表约束中的一列或多列的排序顺序。默认值为 ASC。
  • partition_scheme_name
    分区架构的名称,该分区架构定义要将已分区表的分区映射到的文件组。数据库中必须存在该分区架构。
  • [ partition_column_name**.** ]
    指定对已分区表进行分区所依据的列。该列必须在数据类型、长度和精度方面与 partition_scheme_name 所使用的分区函数中指定的列相匹配。分区函数使用的计算列必须显式标记为 PERSISTED。

    ms174979.note(zh-cn,SQL.90).gif重要提示:
    我们建议您在对分区表的分区列指定 NOT NULL,也对作为 ALTER TABLE...SWITCH 操作的源或目标的非分区表的分区列指定 NOT NULL。这样做,可确保分区依据列上的任何 CHECK 约束不必检查 NULL 值。有关详细信息,请参阅使用分区切换高效传输数据
  • WITH FILLFACTOR **=**fillfactor
    指定数据库引擎存储索引数据时每个索引页的填充程度。用户指定的 fillfactor 值可以为介于 1 至 100 之间的任意值。如果未指定值,则默认值为 0。填充因子值 0 和 100 在所有方面都相同。

    ms174979.note(zh-cn,SQL.90).gif重要提示:
    将 WITH FILLFACTOR = fillfactor 记录为适用于 PRIMARY KEY 或 UNIQUE 约束的唯一索引选项是为了保持向后兼容,但在未来的版本中将不会以此方式进行记录。
  • PAD_INDEX = { ON | OFF }
    如果为 ON,则 FILLFACTOR 指定的可用空间百分比将应用于该索引的中间级别页。如果未指定 OFF 或 FILLFACTOR 值,则考虑到中间级别页的键集,将中间级别页填充到一个近似容量,以留出足够的空间来容纳至少一个索引的最大行。默认值为 OFF。
  • FILLFACTOR **=**fillfactor
    指定一个百分比,指示在索引创建或更改过程中数据库引擎应使每个索引页的叶级别达到的填充程度。fillfactor 必须为介于 1 至 100 之间的整数值。默认值为 0。填充因子值 0 和 100 在所有方面都相同。
  • IGNORE_DUP_KEY = { ON | OFF }
    指定当对唯一聚集索引或唯一非聚集索引的多行插入事务中出现重复键值时的错误响应。如果此参数为 ON 并且其中一行违反了唯一索引,则发出警告消息,并且只有违反了 UNIQUE 索引的行失败。如果为 OFF 并且某行违反了唯一索引,则发出错误信息,并回滚整个 INSERT 事务。在处理 UPDATE 语句时,IGNORE_DUP_KEY 不起作用。默认值为 OFF。
  • STATISTICS_NORECOMPUTE = { ON | OFF }
    如果为 ON,则过期的索引统计信息不会自动重新计算。如果为 OFF,则启用自动统计信息更新。默认值为 OFF。
  • ALLOW_ROW_LOCKS = { ON | OFF }
    如果为 ON,则访问索引时允许使用行锁。数据库引擎确定何时使用行锁。如果为 OFF,则不使用行锁。默认值为 ON。
  • ALLOW_PAGE_LOCKS = { ON | OFF }
    如果为 ON,则访问索引时允许使用页锁。数据库引擎确定何时使用页锁。如果为 OFF,则不使用页锁。默认值为 ON。

备注

在 SQL Server 2005 中,每个数据库最多可包含 20 亿个表,每个表可包含 1,024 列。表的行数及总大小仅受可用存储空间的限制。每行最多包括 8,060 个字节。对于带 varcharnvarcharvarbinarysql_variant 列(导致已定义表的总宽超过 8,060 字节)的表,此限制将放宽。其中每列的长度仍必须在 8,000 字节的限制内,但是它们的总宽可能超过表的 8,060 字节的限制。有关详细信息,请参阅行溢出数据超过 8 KB

每个表最多可以有 249 个非聚集索引和 1 个聚集索引。其中包括为支持表中所定义的 PRIMARY KEY 和 UNIQUE 约束而生成的索引。

通常情况下,为表和索引分配空间时,每次以一个区为增量单位。当创建表或索引时,首先从混合区为其分配页,直到它具有足够的页填满一个统一区。当足够的页填满统一区后,每当当前分配的区填满时,将再为其分配另一个区。若要获得关于由表分配和占用的空间量的报表,请执行 sp_spaceused

数据库引擎在列定义中并不强制以特定的顺序指定 DEFAULT、IDENTITY、ROWGUIDCOL 或列约束。

创建表后,即使 QUOTED IDENTIFIER 选项在创建表时设置为 OFF,该选项在表的元数据中仍存储为 ON。

临时表

可以创建本地临时表和全局临时表。本地临时表仅在当前会话中可见,而全局临时表在所有会话中都可见。临时表不能分区。

本地临时表的名称前面有一个数字符号 (#table_name),而全局临时表的名称前面有两个数字符号 (##table_name)。

SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的值引用临时表,例如:

CREATE TABLE #MyTempTable (cola INT PRIMARY KEY);
INSERT INTO #MyTempTable VALUES (1);

如果在单个存储过程或批处理中创建了多个临时表,则它们必须有不同的名称。

如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则数据库引擎必须能够区分由不同用户创建的表。为此,数据库引擎在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdbsysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的 table_name 不能超过 116 个字符。

除非使用 DROP TABLE 显式删除临时表,否则临时表将在退出其作用域时由系统自动删除:

  • 当存储过程完成时,将自动删除在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。
  • 所有其他本地临时表在当前会话结束时都将被自动删除。
  • 全局临时表在创建此表的会话结束且其他所有任务停止对其引用时将被自动删除。任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。换言之,当创建全局临时表的会话结束时,最后一条引用此表的 Transact-SQL 语句完成后,将自动删除此表。

在存储过程或触发器中创建的本地临时表的名称可以与在调用存储过程或触发器之前创建的临时表名称相同。但是,如果查询引用临时表,而同时有两个同名的临时表,则不定义针对哪个表解析该查询。嵌套存储过程同样可以创建与调用它的存储过程所创建的临时表同名的临时表。但是,为了对其进行修改以解析为在嵌套过程中创建的表,此表必须与调用过程创建的表具有相同的结构和列名。下面的示例说明了这一点。

CREATE PROCEDURE dbo.Test2
AS
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (2);
SELECT Test2Col = x FROM #t;
GO
CREATE PROCEDURE dbo.Test1
AS
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (1);
SELECT Test1Col = x FROM #t;
EXEC Test2;
GO
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (99);
GO
EXEC Test1;
GO

下面是结果集:

(1 row(s) affected)

Test1Col    
----------- 
1           

(1 row(s) affected)

Test2Col    
----------- 
2           

当创建本地或全局临时表时,CREATE TABLE 语法支持除 FOREIGN KEY 约束以外的其他所有约束定义。如果临时表中指定了 FOREIGN KEY 约束,则该语句将返回一条表明已跳过此约束的警告消息。此表仍将创建,但不使用 FOREIGN KEY 约束。在 FOREIGN KEY 约束中不能引用临时表。

建议您使用表变量而不使用临时表。当必须对临时表显式地创建索引时,或多个存储过程或函数必须使用表值时,临时表很有用。通常,表变量可提供更有效的查询处理。有关详细信息,请参阅表 (Transact-SQL)

已分区表

使用 CREATE TABLE 创建已分区表前,必须首先创建分区函数以指定表分区的方式。可使用 CREATE PARTITION FUNCTION (Transact-SQL) 创建分区函数。其次,必须创建分区架构,以指定将保存由分区函数指示的分区的文件组。可使用 CREATE PARTITION SCHEME (Transact-SQL) 创建分区架构。对于已分区表,不能指定用于分隔文件组的 PRIMARY KEY 或 UNIQUE 约束的位置。有关详细信息,请参阅已分区表和已分区索引

PRIMARY KEY 约束

  • 一个表只能包含一个 PRIMARY KEY 约束。
  • 由 PRIMARY KEY 约束生成的索引不会使表中的非聚集索引超过 249 个,聚集索引超过 1 个。
  • 如果没有为 PRIMARY KEY 约束指定 CLUSTERED 或 NONCLUSTERED,并且没有为 UNIQUE 约束指定聚集索引,则将对该 PRIMARY KEY 约束使用 CLUSTERED。
  • 在 PRIMARY KEY 约束中定义的所有列都必须定义为 NOT NULL。如果没有指定为空性,则加入 PRIMARY KEY 约束的所有列的为空性都将设置为 NOT NULL。
  • 如果在 CLR 用户定义类型的列中定义主键,则该类型的实现必须支持二进制排序。有关详细信息,请参阅 CLR User-Defined Types

UNIQUE 约束

  • 如果没有为 UNIQUE 约束指定 CLUSTERED 或 NONCLUSTERED,则默认使用 NONCLUSTERED。
  • 每个 UNIQUE 约束都生成一个索引。UNIQUE 约束的数目不会使表中的非聚集索引超过 249 个,聚集索引超过 1 个。
  • 如果在 CLR 用户定义类型的列中定义唯一约束,则该类型的实现必须支持二进制或基于运算符的排序。有关详细信息,请参阅 CLR User-Defined Types

FOREIGN KEY 约束

  • 如果在 FOREIGN KEY 约束的列中输入非 NULL 值,则此值必须在被引用列中存在;否则,将返回违反外键约束的错误信息。
  • 如果未指定源列,则 FOREIGN KEY 约束适用于前面所讲的列。
  • FOREIGN KEY 约束仅能引用位于同一服务器上的同一数据库中的表。跨数据库的引用完整性必须通过触发器实现。有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)
  • FOREIGN KEY 约束可引用同一表中的其他列。此行为称为自引用。
  • 列级 FOREIGN KEY 约束的 REFERENCES 子句只能列出一个引用列。此列的数据类型必须与定义约束的列的数据类型相同。
  • 表级 FOREIGN KEY 约束的 REFERENCES 子句中引用列的数目必须与约束列列表中的列数相同。每个引用列的数据类型也必须与列表中相应列的数据类型相同。
  • 如果类型为 timestamp 的列是外键或被引用键的一部分,则不能指定 CASCADE、SET NULL 或 SET DEFAULT。
  • 可将 CASCADE、SET NULL、SET DEFAULT 和 NO ACTION 在相互存在引用关系的表上进行组合。如果数据库引擎遇到 NO ACTION,它将停止并回滚相关的 CASCADE、SET NULL 和 SET DEFAULT 操作。如果 DELETE 语句导致 CASCADE、SET NULL、SET DEFAULT 和 NO ACTION 操作的组合,则在数据库引擎检查所有 NO ACTION 前,将应用所有 CASCADE、SET NULL 和 SET DEFAULT 操作。
  • 对于表可包含的引用其他表的 FOREIGN KEY 约束的数目或其他表所拥有的引用特定表的 FOREIGN KEY 约束的数目,数据库引擎都没有预定义的限制。
    尽管如此,可使用的 FOREIGN KEY 约束的实际数目还是受硬件配置以及数据库和应用程序设计的限制。建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。有效的限制还是或多或少取决于应用程序和硬件。在设计数据库和应用程序时应考虑强制 FOREIGN KEY 约束的开销。
  • 对于临时表不强制 FOREIGN KEY 约束。
  • FOREIGN KEY 约束只能引用所引用的表的 PRIMARY KEY 或 UNIQUE 约束中的列或所引用的表上 UNIQUE INDEX 中的列。
  • 如果在 CLR 用户定义类型的列上定义外键,则该类型的实现必须支持二进制排序。有关详细信息,请参阅 CLR User-Defined Types
  • 仅当 FOREIGN KEY 约束引用的主键也定义为类型 varchar(max) 时,才能在此约束中使用类型为 varchar(max) 的列。

DEFAULT 定义

  • 每列只能有一个 DEFAULT 定义。

  • DEFAULT 定义可以包含常量值、函数、SQL-92 niladic 函数或 NULL。下表显示 niladic 函数及其在执行 INSERT 语句时返回的默认值。

    SQL-92 niladic 函数 返回的值

    CURRENT_TIMESTAMP

    当前日期和时间。

    CURRENT_USER

    执行插入的用户的名称。

    SESSION_USER

    执行插入的用户的名称。

    SYSTEM_USER

    执行插入的用户的名称。

    USER

    执行插入的用户的名称。

  • DEFAULT 定义中的 constant_expression 不能引用表中的其他列,也不能引用其他表、视图或存储过程。

  • 不能对数据类型为 timestamp 的列或具有 IDENTITY 属性的列创建 DEFAULT 定义。

  • 如果别名数据类型绑定到默认对象,则不能对该别名数据类型的列创建 DEFAULT 定义。

CHECK 约束

  • 列可以有任意多个 CHECK 约束,并且约束条件中可以包含用 AND 和 OR 组合起来的多个逻辑表达式。列上的多个 CHECK 约束按创建顺序进行验证。
  • 搜索条件必须取值为布尔表达式,并且不能引用其他表。
  • 列级 CHECK 约束只能引用被约束的列,表级 CHECK 约束只能引用同一表中的列。
    当执行 INSERT 和 DELETE 语句时,CHECK CONSTRAINTS 和规则具有相同的数据验证功能。
  • 当列上存在规则和一个或多个 CHECK 约束时,将验证所有限制。
  • 不能在 textntextimage 列上定义 CHECK 约束。

其他约束信息

  • 为约束创建的索引不能用 DROP INDEX 删除;必须用 ALTER TABLE 删除约束。可以用 DBCC DBREINDEX 重建为约束创建的并由其使用的索引。
  • 除了不能以数字符号 (#) 开头以外,约束名称还必须符合标识符规则。如果未提供 constraint_name,则将系统生成的名称分配给约束。约束名将出现在所有与违反约束有关的错误信息中。
  • 当 INSERT、UPDATE 或 DELETE 语句违反约束时,将终止执行该语句。但是,当 SET XACT_ABORT 设置为 OFF 时,如果该语句是显式事务的一部分,则继续处理此事务。当 SET XACT_ABORT 设置为 ON 时,将回滚整个事务。还可以通过检查系统函数 **@@**ERROR,从而在事务定义中使用 ROLLBACK TRANSACTION 语句。
  • 如果 ALLOW_ROW_LOCKS = ON 并且 ALLOW_PAGE_LOCK = ON,则当访问索引时将允许行、页和表级别的锁。数据库引擎将选择相应的锁,并且可以将锁从行锁或页锁升级到表锁。有关详细信息,请参阅锁升级(数据库引擎)。如果 ALLOW_ROW_LOCKS = OFF 并且 ALLOW_PAGE_LOCK = OFF,则当访问索引时只允许表级锁。有关为索引配置锁定粒度的详细信息,请参阅自定义索引的锁定
  • 如果某个表具有 FOREIGN KEY 或 CHECK CONSTRAINTS 及触发器,则将在触发器执行前先检查约束条件。

若要获得关于表及其列的报表,请使用 sp_helpsp_helpconstraint。若要重命名表,请使用 sp_rename。若要获得与表相关的视图和存储过程的报表,请使用 sp_depends

表定义中的为空性规则

列的为空性决定该列中是否允许以空值 (NULL) 作为其数据。NULL 不为零或空白:NULL 表示没有生成任何项或没有提供显式 NULL,它通常暗指该值未知或不可用。

当用 CREATE TABLE 或 ALTER TABLE 语句创建或更改表时,数据库或会话设置会影响且可能覆盖列定义中数据类型的为空性。建议您始终将列显式定义为非计算列的 NULL 或 NOT NULL,或者,如果使用用户定义的数据类型,则建议您允许该列使用此数据类型的默认为空性。

如果未显式指定列的为空性,则遵循下表显示的规则。

列数据类型 规则

别名数据类型

数据库引擎使用创建数据类型时指定的为空性。若要确定数据类型的默认为空性,请使用 sp_help

CLR 用户定义类型

根据列定义确定为空性。

系统提供的数据类型

如果系统提供的数据类型只有一个选项,则优先使用该选项。timestamp 数据类型必须为 NOT NULL。

如果兼容级别小于或等于 65,且列没有显式定义 NULL 或 NOT NULL,则 bit 数据类型默认为 NOT NULL。有关详细信息,请参阅 sp_dbcmptlevel (Transact-SQL)

当任何会话设置通过 SET 设置为 ON 时:

  • 如果 ANSI_NULL_DFLT_ON = ON,则分配 NULL。
  • 如果 ANSI_NULL_DFLT_OFF = ON,则分配 NOT NULL。
  • 当任何数据库设置通过 ALTER DATABASE 进行配置时:
  • 如果 ANSI_NULL_DEFAULT_ON = ON,则分配 NULL。
  • 如果 ANSI_NULL_DEFAULT_OFF = ON,则分配 NOT NULL。
  • 若要查看 ANSI_NULL_DEFAULT 的数据库设置,请使用 sys.databases 目录视图

如果没有为会话设置 ANSI_NULL_DFLT 的任何选项并且数据库设置为默认值(ANSI_NULL_DEFAULT 为 OFF),则分配 SQL Server 默认值 NOT NULL。

如果该列是计算列,则其为空性总是由数据库引擎自动确定。若要查找此类型列的为空性,请使用带 AllowsNull 属性的 COLUMNPROPERTY 函数。

ms174979.note(zh-cn,SQL.90).gif注意:
默认情况下,SQL Server ODBC 驱动程序和用于 SQL Server 的 Microsoft OLE DB 访问接口都将 ANSI_NULL_DFLT_ON 设置为 ON。ODBC 和 OLE DB 用户可以在 ODBC 数据源中配置该设置,或通过应用程序设置的连接特性或属性配置该设置。

权限

需要在数据库中具有 CREATE TABLE 权限,对在其中创建表的架构具有 ALTER 权限。

如果 CREATE TABLE 语句中的任何列被定义为 CLR 用户定义类型,则需要具有对此类型的所有权或 REFERENCES 权限。

如果 CREATE TABLE 语句中的任何列具有与其关联的 XML 架构集合,则需要具有对 XML 架构集合的所有权或 REFERENCES 权限。

示例

A. 使用 PRIMARY KEY 约束

以下示例显示 AdventureWorks 示例数据库中 Employee 表(允许系统提供约束名)的 EmployeeID 列具有聚集索引的 PRIMARY KEY 约束的列定义。

EmployeeID int
PRIMARY KEY CLUSTERED

B. 使用 FOREIGN KEY 约束

FOREIGN KEY 约束用于引用其他表。FOREIGN KEY 可以是单列键或多列键。以下示例显示 SalesOrderHeader 表上引用 SalesPerson 表的单列 FOREIGN KEY 约束。对于单列 FOREIGN KEY 约束,只需要 REFERENCES 子句。

SalesPersonID int NULL
REFERENCES SalesPerson(SalesPersonID)

也可以显式使用 FOREIGN KEY 子句并复述列特性。注意在这两个表中列名不必相同。

FOREIGN KEY (SalesPersonID) REFERENCES SalesPerson(SalesPersonID)

多列键约束作为表约束创建。在 AdventureWorks 数据库中,SpecialOfferProduct 表包含多列 PRIMARY KEY。以下示例显示如何从其他表中引用此键(可选择显式约束名)。

CONSTRAINT FK_SpecialOfferProduct_SalesOrderDetail FOREIGN KEY
 (ProductID, SpecialOfferID)
REFERENCES SpecialOfferProduct (ProductID, SpecialOfferID)

C. 使用 UNIQUE 约束

UNIQUE 约束用于强制非主键列的唯一性。以下示例强制的限制是,Product 表的 Name 列必须唯一。

Name nvarchar(100) NOT NULL
UNIQUE NONCLUSTERED

D. 使用 DEFAULT 定义

使用 INSERT 和 UPDATE 语句时,如果没有提供值,则默认值会提供值。例如,AdventureWorks 数据库可包括一个查找表,此表列出该公司的员工可以填充的不同工作。在描述每个工作的列的下面,如果没有显式输入实际的描述,则字符串默认值可提供一个描述。

DEFAULT 'New Position - title not formalized yet'

除了常量以外,DEFAULT 定义还可以包含函数。使用以下示例获取输入项的当前日期。

DEFAULT (getdate())

niladic 函数扫描也可改善数据完整性。若要跟踪插入行的用户,请使用 USER 的 niladic 函数。不要用括号将 niladic 函数括起来。

DEFAULT USER

E. 使用 CHECK 约束

以下示例显示对于在 Vendor 表的 CreditRating 列中输入的值所做的限制。此约束未命名。

CHECK (CreditRating >= 1 and CreditRating <= 5)

此示例显示一个命名约束,它对于在表的列中输入的字符数据有模式限制。

CONSTRAINT CK_emp_id CHECK (emp_id LIKE 
'[A-Z][A-Z][A-Z][1-9][0-9][0-9][0-9][0-9][FM]' 
OR emp_id LIKE '[A-Z]-[A-Z][1-9][0-9][0-9][0-9][0-9][FM]')

此示例指定这些值必须在特定的列表中或遵循指定的模式。

CHECK (emp_id IN ('1389', '0736', '0877', '1622', '1756')
OR emp_id LIKE '99[0-9][0-9]')

F. 显示完整的表定义

以下示例显示在 AdventureWorks 数据库中创建的 PurchaseOrderDetail 表的完整表定义,其中包含所有约束定义。请注意,若要运行此示例,表架构应改为 dbo

CREATE TABLE [dbo].[PurchaseOrderDetail]
(
    [PurchaseOrderID] [int] NOT NULL
        REFERENCES Purchasing.PurchaseOrderHeader(PurchaseOrderID),
    [LineNumber] [smallint] NOT NULL,
    [ProductID] [int] NULL 
        REFERENCES Production.Product(ProductID),
    [UnitPrice] [money] NULL,
    [OrderQty] [smallint] NULL,
    [ReceivedQty] [float] NULL,
    [RejectedQty] [float] NULL,
    [DueDate] [datetime] NULL,
    [rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL
        CONSTRAINT [DF_PurchaseOrderDetail_rowguid] DEFAULT (newid()),
    [ModifiedDate] [datetime] NOT NULL 
        CONSTRAINT [DF_PurchaseOrderDetail_ModifiedDate] DEFAULT (getdate()),
    [LineTotal]  AS (([UnitPrice]*[OrderQty])),
    [StockedQty]  AS (([ReceivedQty]-[RejectedQty])),
CONSTRAINT [PK_PurchaseOrderDetail_PurchaseOrderID_LineNumber]
    PRIMARY KEY CLUSTERED ([PurchaseOrderID], [LineNumber])
    WITH (IGNORE_DUP_KEY = OFF)
) 
ON [PRIMARY];

G. 创建其 xml 列键入 XML 架构集合的表

以下示例创建一个表,其 xml 列将键入 XML 架构集合 HRResumeSchemaCollectionDOCUMENT 关键字指定 column_name 中数据类型为 xml 的每个实例只能包含一个顶级元素。

USE AdventureWorks;
GO
CREATE TABLE HumanResources.EmployeeResumes 
   (LName nvarchar(25), FName nvarchar(25), 
    Resume xml( DOCUMENT HumanResources.HRResumeSchemaCollection) );

H. 创建已分区表

以下示例创建一个分区函数,将表或索引分为四个分区。然后,此示例创建用于指定保存四个分区的文件组的分区架构。最后,此示例创建使用此分区架构的表。此示例假定数据库中已经存在文件组。

CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000) ;
GO
CREATE PARTITION SCHEME myRangePS1
AS PARTITION myRangePF1
TO (test1fg, test2fg, test3fg, test4fg) ;
GO
CREATE TABLE PartitionTable (col1 int, col2 char(10))
ON myRangePS1 (col1) ;
GO

根据 PartitionTablecol1 列的值,将分区按照下列方式分配。

文件组 test1fg test2fg test3fg test4fg

分区

1

2

3

4

col 1 <= 1

col1 > 1 AND col1 <= 100

col1 > 100 AND col1 <= 1,000

col1 > 1000

G. 在列中使用 uniqueidentifier 数据类型

以下示例创建含有 uniqueidentifier 列的表。该示例使用 PRIMARY KEY 约束以确保用户不会在表中插入重复的值,并在 DEFAULT 约束中使用 NEWID() 函数为新行提供值。将 ROWGUIDCOL 属性应用到 uniqueidentifier 列,以便可以使用 $ROWGUID 关键字对其进行引用。

CREATE TABLE dbo.Globally_Unique_Data
(guid uniqueidentifier CONSTRAINT Guid_Default DEFAULT NEWSEQUENTIALID() ROWGUIDCOL,
    Employee_Name varchar(60)
CONSTRAINT Guid_PK PRIMARY KEY (guid) );

H. 对计算列使用表达式

以下示例显示如何使用用于计算 myavg 计算列的表达式 ((low + high)/2)。

CREATE TABLE dbo.mytable 
( low int, high int, myavg AS (low + high)/2 ) ;

K. 基于用户定义类型列创建计算列

以下示例将创建一个表,其中一列定义为用户定义类型 utf8string,并假设此类型的程序集和类型本身已在当前数据库中创建。另一列基于 utf8string 定义,使用 type(class)utf8stringToString() 方法计算列值。

CREATE TABLE UDTypeTable 
( u utf8string, ustr AS u.ToString() PERSISTED ) ;

I. 对计算列使用 USER_NAME 函数

以下示例在 myuser_name 列中使用 USER_NAME() 函数。

CREATE TABLE dbo.mylogintable
( date_in datetime, user_id int, myuser_name AS USER_NAME() ) ;

请参阅

参考

ALTER TABLE (Transact-SQL)
COLUMNPROPERTY (Transact-SQL)
CREATE INDEX (Transact-SQL)
CREATE RULE (Transact-SQL)
CREATE VIEW (Transact-SQL)
数据类型 (Transact-SQL)
DROP INDEX (Transact-SQL)
DROP RULE (Transact-SQL)
DROP TABLE (Transact-SQL)
CREATE PARTITION FUNCTION (Transact-SQL)
CREATE PARTITION SCHEME (Transact-SQL)
CREATE TYPE (Transact-SQL)
EVENTDATA (Transact-SQL)
sp_depends (Transact-SQL)
sp_help (Transact-SQL)
sp_helpconstraint (Transact-SQL)
sp_rename (Transact-SQL)
sp_spaceused (Transact-SQL)

帮助和信息

获取 SQL Server 2005 帮助

更改历史记录

发布日期 历史记录

2006 年 12 月 12 日

更改的内容:
  • 明确了语法关系图 <computed_column_definition> 部分中 ON 子句的位置。
新增内容:
  • 针对 partition_column_name 参数添加了一条说明:建议对已分区表的分区列以及作为 ALTER TABLE...SWITCH 操作的源或目标的非分区表的分区列指定 NOT NULL。

2006 年 4 月 14 日

更改的内容:
  • 更新了示例 I 以使用 NEWSEQUENTIALID 函数和 ROWGUIDCOL 属性。
  • 澄清了使用 ROWGUIDCOL 属性的目的,除了 NEWID 以外还添加了使用 NEWSEQUENTIALID 的参考。
  • 删除了以前记录的将 CASCADE 用于预计算分区(以便合并复制)时所受的限制。