CREATE TABLE
Запрос CREATE TABLE может иметь несколько форм, которые используются в зависимости от контекста и решаемых задач.
По умолчанию таблицы создаются на текущем сервере. Распределенные DDL запросы создаются с помощью секции ON CLUSTER , которая описана отдельно.
Варианты синтаксиса
С описанием структуры
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr1] [compression_codec] [TTL expr1], name2 [type2] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr2] [compression_codec] [TTL expr2], ... ) ENGINE = engine
Создаёт таблицу с именем name в БД db или текущей БД, если db не указана, со структурой, указанной в скобках, и движком engine. Структура таблицы представляет список описаний столбцов. Индексы, если поддерживаются движком, указываются в качестве параметров для движка таблицы.
Описание столбца, это name type , в простейшем случае. Пример: RegionID UInt32 . Также могут быть указаны выражения для значений по умолчанию — смотрите ниже.
При необходимости можно указать первичный ключ с одним или несколькими ключевыми выражениями.
Со структурой, аналогичной другой таблице
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS [db2.]name2 [ENGINE = engine]
Создаёт таблицу с такой же структурой, как другая таблица. Можно указать другой движок для таблицы. Если движок не указан, то будет выбран такой же движок, как у таблицы db2.name2 .
Из табличной функции
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS table_function()
Создаёт таблицу с такой же структурой и данными, как результат соответствующей табличной функции. Созданная таблица будет работать так же, как и указанная табличная функция.
Из запроса SELECT
CREATE TABLE [IF NOT EXISTS] [db.]table_name[(name1 [type1], name2 [type2], ...)] ENGINE = engine AS SELECT ...
Создаёт таблицу со структурой, как результат запроса SELECT , с движком engine , и заполняет её данными из SELECT . Также вы можете явно задать описание столбцов.
Если таблица уже существует и указано IF NOT EXISTS , то запрос ничего не делает.
После секции ENGINE в запросе могут использоваться и другие секции в зависимости от движка. Подробную документацию по созданию таблиц смотрите в описаниях движков таблиц.
Пример
CREATE TABLE t1 (x String) ENGINE = Memory AS SELECT 1; SELECT x, toTypeName(x) FROM t1;
┌─x─┬─toTypeName(x)─┐ │ 1 │ String │ └───┴───────────────┘
Модификатор NULL или NOT NULL
Модификатор NULL или NOT NULL , указанный после типа данных в определении столбца, позволяет или не позволяет типу данных быть Nullable.
Если тип не Nullable и указан модификатор NULL , то столбец будет иметь тип Nullable ; если NOT NULL , то не Nullable . Например, INT NULL то же, что и Nullable(INT) . Если тип Nullable и указаны модификаторы NULL или NOT NULL , то будет вызвано исключение.
Значения по умолчанию
В описании столбца, может быть указано выражение для значения по умолчанию, одного из следующих видов: DEFAULT expr , MATERIALIZED expr , ALIAS expr . Пример: URLDomain String DEFAULT domain(URL) .
Если выражение для значения по умолчанию не указано, то в качестве значений по умолчанию будут использоваться нули для чисел, пустые строки для строк, пустые массивы для массивов, а также 0000-00-00 для дат и 0000-00-00 00:00:00 для дат с временем. NULL-ы не поддерживаются.
В случае, если указано выражение по умолчанию, то указание типа столбца не обязательно. При отсутствии явно указанного типа, будет использован тип выражения по умолчанию. Пример: EventDate DEFAULT toDate(EventTime) — для столбца EventDate будет использован тип Date.
При наличии явно указанного типа данных и выражения по умолчанию, это выражение будет приводиться к указанному типу с использованием функций приведения типа. Пример: Hits UInt32 DEFAULT 0 — имеет такой же смысл, как Hits UInt32 DEFAULT toUInt32(0) .
В качестве выражения для умолчания, может быть указано произвольное выражение от констант и столбцов таблицы. При создании и изменении структуры таблицы, проверяется, что выражения не содержат циклов. При INSERT-е проверяется разрешимость выражений — что все столбцы, из которых их можно вычислить, переданы.
DEFAULT
Обычное значение по умолчанию. Если в запросе INSERT не указан соответствующий столбец, то он будет заполнен путём вычисления соответствующего выражения.
MATERIALIZED
Материализованное выражение. Такой столбец не может быть указан при INSERT, то есть, он всегда вычисляется. При INSERT без указания списка столбцов, такие столбцы не рассматриваются. Также этот столбец не подставляется при использовании звёздочки в запросе SELECT. Это необходимо, чтобы сохранить инвариант, что дамп, полученный путём SELECT * , можно вставить обратно в таблицу INSERT-ом без указания списка столбцов.
EPHEMERAL
Эфемерное выражение. Такой столбец не хранится в таблице и не может быть получен в запросе SELECT, но на него можно ссылаться в выражениях по умолчанию запроса CREATE. Если значение по умолчанию expr не указано, то тип колонки должен быть специфицирован. INSERT без списка столбцов игнорирует этот столбец, таким образом сохраняется инвариант — т.е. дамп, полученный путём SELECT * , можно вставить обратно в таблицу INSERT-ом без указания списка столбцов.
ALIAS
Синоним. Такой столбец вообще не хранится в таблице. Его значения не могут быть вставлены в таблицу, он не подставляется при использовании звёздочки в запросе SELECT. Он может быть использован в SELECT-ах — в таком случае, во время разбора запроса, алиас раскрывается.
При добавлении новых столбцов с помощью запроса ALTER, старые данные для этих столбцов не записываются. Вместо этого, при чтении старых данных, для которых отсутствуют значения новых столбцов, выполняется вычисление выражений по умолчанию на лету. При этом, если выполнение выражения требует использования других столбцов, не указанных в запросе, то эти столбцы будут дополнительно прочитаны, но только для тех блоков данных, для которых это необходимо.
Если добавить в таблицу новый столбец, а через некоторое время изменить его выражение по умолчанию, то используемые значения для старых данных (для данных, где значения не хранились на диске) поменяются. Также заметим, что при выполнении фоновых слияний, данные для столбцов, отсутствующих в одном из сливаемых кусков, записываются в объединённый кусок.
Отсутствует возможность задать значения по умолчанию для элементов вложенных структур данных.
Первичный ключ
Вы можете определить первичный ключ при создании таблицы. Первичный ключ может быть указан двумя способами:
- в списке столбцов:
CREATE TABLE db.table_name ( name1 type1, name2 type2, ..., PRIMARY KEY(expr1[, expr2,...])] ) ENGINE = engine;
- вне списка столбцов:
CREATE TABLE db.table_name ( name1 type1, name2 type2, ... ) ENGINE = engine PRIMARY KEY(expr1[, expr2,...]);
CREATE TABLE AS SELECT
CREATE TABLE AS SELECT (CTAS) es una de las características más importantes de T-SQL disponibles. Se trata de una operación completamente en paralelo que crea una nueva tabla basada en la salida de una instrucción SELECT. CTAS es la forma más sencilla y rápida de crear una copia de una tabla.
Por ejemplo, use CTAS para lo siguiente:
- Volver a crear una tabla con una columna de distribución de hash diferente.
- Volver a crear una tabla como replicada.
- Crear un índice de almacén de columnas en solo algunas columnas de la tabla.
- Consultar o importar datos externos.
Dado que CTAS se agrega a las funcionalidades para crear tablas, en este tema se procura no repetir el tema CREATE TABLE. En su lugar, se describen las diferencias entre las instrucciones CTAS y CREATE TABLE. Para obtener todos los detalles sobre CREATE TABLE, vea la instrucción CREATE TABLE (Azure Synapse Analytics).
- El grupo de SQL sin servidor no admite esta sintaxis en Azure Synapse Analytics.
- CTAS se admite en el almacenamiento de Microsoft Fabric.
Sintaxis
CREATE TABLE < database_name.schema_name.table_name | schema_name.table_name | table_name >[ ( column_name [ . n ] ) ] WITH ( -- required [ , [ . n ] ] ) AS OPTION [;] ::= < DISTRIBUTION = HASH ( distribution_column_name ) | DISTRIBUTION = HASH ( [distribution_column_name [, . n]] ) | DISTRIBUTION = ROUND_ROBIN | DISTRIBUTION = REPLICATE > ::= < CLUSTERED COLUMNSTORE INDEX --default for Synapse Analytics | CLUSTERED COLUMNSTORE INDEX ORDER (column[. n]) | HEAP --default for Parallel Data Warehouse | CLUSTERED INDEX ( < index_column_name [ ASC | DESC ] >[ . n ] ) --default is ASC > | PARTITION ( partition_column_name RANGE [ LEFT | RIGHT ] --default is LEFT FOR VALUES ( [ boundary_value [. n] ] ) ) ::= [ WITH [ . n ] ] SELECT select_criteria ::=
Argumentos
Para más información, vea la sección Argumentos de CREATE TABLE.
Opciones de columna
column_name [ . n ]
Los nombres de columna no permiten las opciones de columna mencionadas en CREATE TABLE. En su lugar, puede proporcionar una lista opcional de uno o más nombres de columna para la nueva tabla. Las columnas de la nueva tabla usan los nombres que especifique. Al especificar nombres de columna, el número de columnas de la lista de columnas debe coincidir con el número de columnas de los resultados de selección. Si no especifica nombres de columna, la nueva tabla de destino usa los nombres de columna de los resultados de la instrucción de selección.
No se pueden especificar otras opciones de columna, como tipos de datos, intercalación o la nulabilidad. Cada uno de estos atributos se deriva de los resultados de la instrucción SELECT . Aun así, puede usar la instrucción SELECT para cambiar los atributos. Para obtener un ejemplo, vea Usar CTAS para cambiar los atributos de columna.
Opciones de distribución de tabla
Para obtener más información y entender cómo elegir la mejor columna de distribución, vea la sección Opciones de distribución de tabla en CREATE TABLE. Para obtener recomendaciones sobre qué distribución elegir para una tabla en función del uso real o las consultas de ejemplo, consulte Asesor de distribución de Azure Synapse SQL.
DISTRIBUTION = HASH ( distribution_column_name ) | ROUND_ROBIN | REPLICATE La instrucción CTAS requiere una opción de distribución y no tiene valores predeterminados. Es diferente de CREATE TABLE, que tiene valores predeterminados.
DISTRIBUTION = HASH ( [distribution_column_name [, . n]] ) Distribuye las filas basadas en los valores hash de hasta ocho columnas, lo que permite una distribución más uniforme de los datos de la tabla base, reduce la asimetría de datos en el tiempo y mejora el rendimiento de las consultas.
- Para habilitar la característica, cambie el nivel de compatibilidad de la base de datos a 50 mediante este comando. Para obtener más información sobre cómo establecer el nivel de compatibilidad de la base de datos, consulte ALTER DATABASE SCOPED CONFIGURATION. Por ejemplo: ALTER DATABASE SCOPED CONFIGURATION SET DW_COMPATIBILITY_LEVEL = 50;
- Para deshabilitar la función de distribución de varias columnas (MCD), ejecute este comando para cambiar el nivel de compatibilidad de la base de datos a AUTO. Por ejemplo: ALTER DATABASE SCOPED CONFIGURATION SET DW_COMPATIBILITY_LEVEL = AUTO; Las tablas MCD existentes se conservarán pero se volverán ilegibles. Las consultas sobre tablas de MCD devolverán este error: Related table/view is not readable because it distributes data on multiple columns and multi-column distribution is not supported by this product version or this feature is disabled.
- Para recuperar el acceso a las tablas MCD, habilite la característica de nuevo.
- Para cargar datos en una tabla MCD, use la instrucción CTAS y el origen de datos deben ser tablas de Synapse SQL.
- No se admite CTAS en las tablas de destino de MCD HEAP. En su lugar, use INSERT SELECT como solución alternativa para cargar datos en tablas de MCD HEAP.
Para obtener más información y entender cómo elegir la mejor columna de distribución, vea la sección Opciones de distribución de tabla en CREATE TABLE.
Para obtener recomendaciones sobre la mejor distribución que se puede usar en función de las cargas de trabajo, consulte Asesor de distribución de Azure Synapse SQL.
Opciones de partición de tabla
La instrucción CTAS crea una tabla sin particiones de forma predeterminada, incluso si la tabla de origen tiene particiones. Para crear una tabla con particiones con la instrucción CTAS, debe especificar la opción de partición.
Para más información, vea la sección Opciones de partición de tabla en CREATE TABLE.
Instrucción SELECT
La instrucción SELECT es la diferencia fundamental entre CTAS y CREATE TABLE.
WITH common_table_expression
Especifica un conjunto de resultados temporal con nombre, conocido como expresión de tabla común (CTE). Para más información, consulte WITH common_table_expression (Transact-SQL).
SELECT select_criteria
Rellena la nueva tabla con los resultados de una instrucción SELECT. select_criteria es el cuerpo de la instrucción SELECT que determina qué datos se copian en la nueva tabla. Para más información sobre las instrucciones SELECT, consulte SELECT (Transact-SQL).
Sugerencia de consulta
Los usuarios pueden establecer MAXDOP en un valor entero para controlar el grado máximo de paralelismo. Cuando MAXDOP se establece en 1, la consulta se ejecuta en un único subproceso.
Permisos
CTAS requiere el permiso SELECT en todos los objetos a los que hace referencia en select_criteria.
Para conocer los permisos para crear una tabla, vea Permisos en CREATE TABLE.
Observaciones
Para más información, vea Notas generales en CREATE TABLE.
Limitaciones y restricciones
Se puede crear un índice de almacén de columnas agrupado y ordenado en columnas de cualquier tipo de datos que se admita en Azure Synapse Analytics, excepto en columnas de cadena.
SET ROWCOUNT (Transact-SQL) no tiene ningún efecto en CTAS. Para lograr un comportamiento similar, use TOP (Transact-SQL).
Para más información, vea Limitaciones y restricciones en CREATE TABLE.
Comportamiento de bloqueo
Para más información, vea Comportamiento de bloqueo en CREATE TABLE.
Rendimiento
Para una tabla distribuida de hash, puede usar CTAS para seleccionar una columna de distribución diferente a fin de obtener un mejor rendimiento de las combinaciones y las agregaciones. Si su objetivo no es seleccionar una columna de distribución diferente, tendrá el mejor rendimiento de CTAS si especifica la misma columna de distribución, ya que de este modo evitará que se redistribuyan las filas.
Si usa CTAS para crear una tabla y el rendimiento no es un factor importante, puede especificar ROUND_ROBIN para evitar tener que elegir una columna de distribución.
Para evitar el movimiento de datos en las consultas posteriores, puede especificar REPLICATE a costa de que aumente el almacenamiento para cargar una copia completa de la tabla en cada nodo de ejecución.
Ejemplos para copiar una tabla
A. Uso de CTAS para copiar una tabla
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
Quizás uno de los usos más comunes de CTAS es crear una copia de una tabla para poder cambiar el DDL. Si, por ejemplo, creó la tabla inicialmente como ROUND_ROBIN y ahora quiere cambiarla a una tabla distribuida en una columna, cambiaría la columna de distribución con CTAS . CTAS también se puede usar para cambiar los tipos de particiones, indexación o columna.
Supongamos que creó esta tabla especificando HEAP y usando el tipo de distribución predeterminado de ROUND_ROBIN .
CREATE TABLE FactInternetSales ( ProductKey INT NOT NULL, OrderDateKey INT NOT NULL, DueDateKey INT NOT NULL, ShipDateKey INT NOT NULL, CustomerKey INT NOT NULL, PromotionKey INT NOT NULL, CurrencyKey INT NOT NULL, SalesTerritoryKey INT NOT NULL, SalesOrderNumber NVARCHAR(20) NOT NULL, SalesOrderLineNumber TINYINT NOT NULL, RevisionNumber TINYINT NOT NULL, OrderQuantity SMALLINT NOT NULL, UnitPrice MONEY NOT NULL, ExtendedAmount MONEY NOT NULL, UnitPriceDiscountPct FLOAT NOT NULL, DiscountAmount FLOAT NOT NULL, ProductStandardCost MONEY NOT NULL, TotalProductCost MONEY NOT NULL, SalesAmount MONEY NOT NULL, TaxAmt MONEY NOT NULL, Freight MONEY NOT NULL, CarrierTrackingNumber NVARCHAR(25), CustomerPONumber NVARCHAR(25) ) WITH( HEAP, DISTRIBUTION = ROUND_ROBIN );Ahora quiere crear una copia de esta tabla con un índice de almacén de columnas agrupado para poder aprovechar el rendimiento de las tablas del almacén de columnas agrupado. También quiere distribuir esta tabla en ProductKey , ya que prevé combinaciones en esta columna y quiere evitar el movimiento de datos durante las mismas en ProductKey . Por último, también quiere agregar la creación de particiones en OrderDateKey , para eliminar rápidamente datos antiguos mediante la anulación de particiones anteriores. A continuación, se muestra la instrucción CTAS que copiaría la tabla antigua en una tabla nueva:
CREATE TABLE FactInternetSales_new WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = HASH(ProductKey), PARTITION ( OrderDateKey RANGE RIGHT FOR VALUES ( 20000101,20010101,20020101,20030101,20040101,20050101,20060101,20070101,20080101,20090101, 20100101,20110101,20120101,20130101,20140101,20150101,20160101,20170101,20180101,20190101, 20200101,20210101,20220101,20230101,20240101,20250101,20260101,20270101,20280101,20290101 ) ) ) AS SELECT * FROM FactInternetSales;Por último, puede cambiar el nombre de las tablas para intercambiar la tabla nueva y, después, anular la tabla antigua.
RENAME OBJECT FactInternetSales TO FactInternetSales_old; RENAME OBJECT FactInternetSales_new TO FactInternetSales; DROP TABLE FactInternetSales_old;Ejemplos de opciones de columna
B. Usar CTAS para cambiar los atributos de columna
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
En este ejemplo se usa CTAS para cambiar los tipos de datos, la nulabilidad y la intercalación de varias columnas en la tabla DimCustomer2 .
-- Original table CREATE TABLE [dbo].[DimCustomer2] ( [CustomerKey] INT NOT NULL, [GeographyKey] INT NULL, [CustomerAlternateKey] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ) WITH (CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = HASH([CustomerKey])); -- CTAS example to change data types, nullability, and column collations CREATE TABLE test WITH (HEAP, DISTRIBUTION = ROUND_ROBIN) AS SELECT CustomerKey AS CustomerKeyNoChange, CustomerKey*1 AS CustomerKeyChangeNullable, CAST(CustomerKey AS DECIMAL(10,2)) AS CustomerKeyChangeDataTypeNullable, ISNULL(CAST(CustomerKey AS DECIMAL(10,2)),0) AS CustomerKeyChangeDataTypeNotNullable, GeographyKey AS GeographyKeyNoChange, ISNULL(GeographyKey,0) AS GeographyKeyChangeNotNullable, CustomerAlternateKey AS CustomerAlternateKeyNoChange, CASE WHEN CustomerAlternateKey = CustomerAlternateKey THEN CustomerAlternateKey END AS CustomerAlternateKeyNullable, CustomerAlternateKey COLLATE Latin1_General_CS_AS_KS_WS AS CustomerAlternateKeyChangeCollation FROM [dbo].[DimCustomer2] -- Resulting table CREATE TABLE [dbo].[test] ( [CustomerKeyNoChange] INT NOT NULL, [CustomerKeyChangeNullable] INT NULL, [CustomerKeyChangeDataTypeNullable] DECIMAL(10, 2) NULL, [CustomerKeyChangeDataTypeNotNullable] DECIMAL(10, 2) NOT NULL, [GeographyKeyNoChange] INT NULL, [GeographyKeyChangeNotNullable] INT NOT NULL, [CustomerAlternateKeyNoChange] NVARCHAR(15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [CustomerAlternateKeyNullable] NVARCHAR(15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [CustomerAlternateKeyChangeCollation] NVARCHAR(15) COLLATE Latin1_General_CS_AS_KS_WS NOT NULL ) WITH (DISTRIBUTION = ROUND_ROBIN);Como paso final, puede usar RENAME (Transact-SQL) para cambiar los nombres de tabla. Esto hace que DimCustomer2 sea la nueva tabla.
RENAME OBJECT DimCustomer2 TO DimCustomer2_old; RENAME OBJECT test TO DimCustomer2; DROP TABLE DimCustomer2_old;Ejemplos de distribución de la tabla
C. Usar CTAS para cambiar el método de distribución de una tabla
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
En este sencillo ejemplo se muestra cómo cambiar el método de distribución de una tabla. Para mostrar la mecánica de cómo se hace, cambia una tabla distribuida de hash a round robin y, después, cambia la tabla round robin de nuevo a distribuida de hash. La tabla final coincide con la tabla original.
En la mayoría de los casos no es necesario convertir una tabla distribuida de hash en una tabla round robin. A menudo, deberá cambiar una tabla round robin a una tabla distribuida de hash. Por ejemplo, es posible que cargue inicialmente una tabla nueva como round robin y, después, la mueva a una tabla distribuida de hash para obtener un mejor rendimiento de combinación.
En este ejemplo se usa la base de datos de ejemplo AdventureWorksDW. Para cargar la versión de Azure Synapse Analytics, consulte Inicio rápido: Creación y consulta de un grupo de SQL dedicado (anteriormente SQL DW) en Azure Synapse Analytics mediante Azure Portal.
-- DimSalesTerritory is hash-distributed. -- Copy it to a round-robin table. CREATE TABLE [dbo].[myTable] WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = ROUND_ROBIN ) AS SELECT * FROM [dbo].[DimSalesTerritory]; -- Switch table names RENAME OBJECT [dbo].[DimSalesTerritory] to [DimSalesTerritory_old]; RENAME OBJECT [dbo].[myTable] TO [DimSalesTerritory]; DROP TABLE [dbo].[DimSalesTerritory_old];Después, cámbiela de nuevo a una tabla distribuida de hash.
-- You just made DimSalesTerritory a round-robin table. -- Change it back to the original hash-distributed table. CREATE TABLE [dbo].[myTable] WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = HASH(SalesTerritoryKey) ) AS SELECT * FROM [dbo].[DimSalesTerritory]; -- Switch table names RENAME OBJECT [dbo].[DimSalesTerritory] to [DimSalesTerritory_old]; RENAME OBJECT [dbo].[myTable] TO [DimSalesTerritory]; DROP TABLE [dbo].[DimSalesTerritory_old];D. Usar CTAS para convertir una tabla en una tabla replicada
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
En este ejemplo se convierten tablas round robin o distribuidas de hash en una tabla replicada. En este ejemplo en concreto, el método anterior de cambiar el tipo de distribución va un paso más allá. Dado que DimSalesTerritory es una dimensión y es probable que sea una tabla más pequeña, puede volver a crear la tabla como replicada para evitar el movimiento de datos al combinarla con otras tablas.
-- DimSalesTerritory is hash-distributed. -- Copy it to a replicated table. CREATE TABLE [dbo].[myTable] WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = REPLICATE ) AS SELECT * FROM [dbo].[DimSalesTerritory]; -- Switch table names RENAME OBJECT [dbo].[DimSalesTerritory] to [DimSalesTerritory_old]; RENAME OBJECT [dbo].[myTable] TO [DimSalesTerritory]; DROP TABLE [dbo].[DimSalesTerritory_old];E. Usar CTAS para crear una tabla con menos columnas
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
En el ejemplo siguiente se crea una tabla distribuida round robin denominada myTable (c, ln) . La nueva tabla solo tiene dos columnas. Usa los alias de columna en la instrucción SELECT para los nombres de las columnas.
CREATE TABLE myTable WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = ROUND_ROBIN ) AS SELECT CustomerKey AS c, LastName AS ln FROM dimCustomer;Ejemplos de sugerencias de consulta
F. Usar una sugerencia de consulta con CREATE TABLE AS SELECT (CTAS)
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
Esta consulta muestra la sintaxis básica para usar una sugerencia de combinación de consulta con la instrucción CTAS. Una vez enviada la consulta, Azure Synapse Analytics aplica la estrategia de combinación hash al generar el plan de consulta para cada distribución individual. Para obtener más información sobre la sugerencia de consulta de combinación hash, vea OPTION Clause (Transact-SQL).
CREATE TABLE dbo.FactInternetSalesNew WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = ROUND_ROBIN ) AS SELECT T1.* FROM dbo.FactInternetSales T1 JOIN dbo.DimCustomer T2 ON ( T1.CustomerKey = T2.CustomerKey ) OPTION ( HASH JOIN );Ejemplos de tablas externas
G. Usar CTAS para importar datos de Azure Blob Storage
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
Para importar datos de una tabla externa, use CREATE TABLE AS SELECT para hacer una selección en la tabla externa. La sintaxis para seleccionar datos de una tabla externa en Azure Synapse Analytics es igual que la sintaxis para seleccionar datos de una tabla normal.
En el ejemplo siguiente se define una tabla externa en los datos de una cuenta de Azure Blob Storage. Después, se usa CREATE TABLE AS SELECT para hacer una selección en la tabla externa. De este modo se importan los datos de los archivos delimitados por texto de Azure Blob Storage y se almacenan en una nueva tabla de Azure Synapse Analytics.
--Use your own processes to create the text-delimited files on Azure Blob Storage. --Create the external table called ClickStream. CREATE EXTERNAL TABLE ClickStreamExt ( url VARCHAR(50), event_date DATE, user_IP VARCHAR(50) ) WITH ( LOCATION='/logs/clickstream/2015/', DATA_SOURCE = MyAzureStorage, FILE_FORMAT = TextFileFormat) ; --Use CREATE TABLE AS SELECT to import the Azure Blob Storage data into a new --Synapse Analytics table called ClickStreamData CREATE TABLE ClickStreamData WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = HASH (user_IP) ) AS SELECT * FROM ClickStreamExt ;H. Usar CTAS para importar datos de Hadoop de una tabla externa
Se aplica a: Sistema de la plataforma de análisis (PDW)
Para importar datos de una tabla externa, basta con que use CREATE TABLE AS SELECT para hacer una selección en la tabla externa. La sintaxis para seleccionar datos de una tabla externa en Sistema de la plataforma de análisis (PDW) es igual que la sintaxis para seleccionar datos de una tabla normal.
En el ejemplo siguiente se define una tabla externa en un clúster de Hadoop. Después, se usa CREATE TABLE AS SELECT para hacer una selección en la tabla externa. De este modo se importan los datos de los archivos delimitados de texto de Hadoop y se almacenan los datos en una nueva tabla de Sistema de la plataforma de análisis (PDW).
-- Create the external table called ClickStream. CREATE EXTERNAL TABLE ClickStreamExt ( url VARCHAR(50), event_date DATE, user_IP VARCHAR(50) ) WITH ( LOCATION = 'hdfs://MyHadoop:5000/tpch1GB/employee.tbl', FORMAT_OPTIONS ( FIELD_TERMINATOR = '|') ) ; -- Use your own processes to create the Hadoop text-delimited files -- on the Hadoop Cluster. -- Use CREATE TABLE AS SELECT to import the Hadoop data into a new -- table called ClickStreamPDW CREATE TABLE ClickStreamPDW WITH ( CLUSTERED COLUMNSTORE INDEX, DISTRIBUTION = HASH (user_IP) ) AS SELECT * FROM ClickStreamExt ;Ejemplos del uso de CTAS para reemplazar código de SQL Server
Use CTAS para hallar soluciones temporales para algunas características no admitidas. Además de permitirle ejecutar el código en el almacén de datos, la reescritura del código existente para usar CTAS suele mejorar el rendimiento. Esto se debe a su diseño totalmente paralelizado.
Intente dar prioridad a CTAS. Lo más recomendable es resolver los problemas mediante CTAS , incluso si como resultado debe escribir más datos.
I. Usar CTAS en lugar de SELECT..EN
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
El código de SQL Server suele usar SELECT..INTO para rellenar una tabla con los resultados de una instrucción SELECT. Este es un ejemplo de una instrucción SELECT..INTO de SQL Server.
SELECT * INTO #tmp_fct FROM [dbo].[FactInternetSales]Esta sintaxis no se admite en Azure Synapse Analytics y en el almacenamiento de datos paralelos. En este ejemplo se muestra cómo reescribir la anterior instrucción SELECT..INTO como una instrucción CTAS. Puede elegir cualquiera de las opciones DISTRIBUTION que se describen en la sintaxis CTAS. En este ejemplo se usa el método de distribución ROUND_ROBIN.
CREATE TABLE #tmp_fct WITH ( DISTRIBUTION = ROUND_ROBIN ) AS SELECT * FROM [dbo].[FactInternetSales] ;J. Usar CTAS para simplificar las instrucciones de fusión
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
Las instrucciones de fusión se pueden sustituir, al menos en parte, mediante CTAS . Es posible consolidar INSERT y UPDATE en una única instrucción. Los registros eliminados deben cerrarse en una segunda instrucción.
A continuación se muestra un ejemplo de UPSERT :
CREATE TABLE dbo.[DimProduct_upsert] WITH ( DISTRIBUTION = HASH([ProductKey]) , CLUSTERED INDEX ([ProductKey]) ) AS -- New rows and new versions of rows SELECT s.[ProductKey] , s.[EnglishProductName] , s.[Color] FROM dbo.[stg_DimProduct] AS s UNION ALL -- Keep rows that are not being touched SELECT p.[ProductKey] , p.[EnglishProductName] , p.[Color] FROM dbo.[DimProduct] AS p WHERE NOT EXISTS ( SELECT * FROM [dbo].[stg_DimProduct] s WHERE s.[ProductKey] = p.[ProductKey] ) ; RENAME OBJECT dbo.[DimProduct] TO [DimProduct_old]; RENAME OBJECT dbo.[DimProduct_upsert] TO [DimProduct];K. establezca explícitamente el tipo de datos y la nulabilidad de salida
Se aplica a: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
Al migrar código de SQL Server a Azure Synapse Analytics, puede encontrarse con este tipo de patrón de codificación:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 CREATE TABLE result (result DECIMAL(7,2) NOT NULL ) WITH (DISTRIBUTION = ROUND_ROBIN) INSERT INTO result SELECT @d*@f ;Instintivamente pensará que debe migrar este código a una instrucción CTAS, y tendría razón. Sin embargo, existe un problema oculto aquí.
El código siguiente NO produce el mismo resultado:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 ; CREATE TABLE ctas_r WITH (DISTRIBUTION = ROUND_ROBIN) AS SELECT @d*@f as result ;Observe que la columna «result» traslada el tipo de datos y los valores de nulabilidad de la expresión. Esto puede provocar sutiles variaciones en los valores si no tiene cuidado.
Pruebe por ejemplo lo siguiente:
SELECT result,result*@d from result ; SELECT result,result*@d from ctas_r ;El valor almacenado para el resultado es diferente. Dado que el valor almacenado en la columna de resultados se usa en otras expresiones, el error es todavía mayor.
Esto es importante para las migraciones de datos. Aunque se puede decir que la segunda consulta es más precisa, hay un problema. Los datos serían diferentes en comparación con el sistema de origen, lo que produce problemas de integridad en la migración. Este es uno de los pocos casos en los que la respuesta «incorrecta» es en realidad la correcta.
El motivo por el que vemos esta discrepancia entre los dos resultados se debe a la conversión de tipos implícita. En el primer ejemplo, la tabla define la definición de columna. Cuando se inserta la fila, se realiza una conversión de tipos implícita. En el segundo ejemplo no hay ninguna conversión de tipos implícita, ya que la expresión define el tipo de datos de la columna. Observe también que la columna del segundo ejemplo se ha definido como una columna que acepta valores NULL mientras que en el primer ejemplo no. Al crear la tabla en el primer ejemplo, se definió explícitamente la nulabilidad de la columna. En el segundo ejemplo, esto le correspondía a la expresión, lo que conllevaba una definición NULL de forma predeterminada.
Para resolver estos problemas, debe establecer explícitamente la conversión de tipos y la nulabilidad en la parte SELECT de la instrucción CTAS . No puede establecer estas propiedades en la parte de creación de la tabla.
En este ejemplo se muestra cómo corregir el código:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 CREATE TABLE ctas_r WITH (DISTRIBUTION = ROUND_ROBIN) AS SELECT ISNULL(CAST(@d*@f AS DECIMAL(7,2)),0) as resultTenga en cuenta lo siguiente en el ejemplo:
- Podían haberse usado CAST o CONVERT.
- Se usa ISNULL para forzar la nulabilidad, no COALESCE.
- ISNULL es la función más externa.
- La segunda parte de ISNULL es una constante, es decir, 0 .
Para que la nulabilidad se establezca correctamente, es fundamental usar ISNULL , no COALESCE . COALESCE no es una función determinista, por lo que el resultado de la expresión siempre aceptará valores NULL. ISNULL es diferente, ya que es determinista. Por lo tanto, cuando la segunda parte de la función ISNULL es una constante o un literal, el valor resultante será NOT NULL.
Esta sugerencia no solo es útil para garantizar la integridad de los cálculos, sino que también es importante para la modificación de particiones de tabla. Imagine que ha definido como hecho esta tabla:
CREATE TABLE [dbo].[Sales] ( [date] INT NOT NULL , [product] INT NOT NULL , [store] INT NOT NULL , [quantity] INT NOT NULL , [price] MONEY NOT NULL , [amount] MONEY NOT NULL ) WITH ( DISTRIBUTION = HASH([product]) , PARTITION ( [date] RANGE RIGHT FOR VALUES (20000101,20010101,20020101 ,20030101,20040101,20050101 ) ) ) ;Pero el campo de valor es una expresión calculada, no forma parte del origen de datos.
Para crear el conjunto de datos con particiones, tenga en cuenta el ejemplo siguiente:
CREATE TABLE [dbo].[Sales_in] WITH ( DISTRIBUTION = HASH([product]) , PARTITION ( [date] RANGE RIGHT FOR VALUES (20000101,20010101 ) ) ) AS SELECT [date] , [product] , [store] , [quantity] , [price] , [quantity]*[price] AS [amount] FROM [stg].[source] OPTION (LABEL = 'CTAS : Partition IN table : Create') ;La consulta se ejecutaría perfectamente. El problema se produce al intentar realizar la modificación de particiones. Las definiciones de la tabla no coinciden. Para que las definiciones de tabla coincidan, es necesario modificar la instrucción CTAS.
CREATE TABLE [dbo].[Sales_in] WITH ( DISTRIBUTION = HASH([product]) , PARTITION ( [date] RANGE RIGHT FOR VALUES (20000101,20010101 ) ) ) AS SELECT [date] , [product] , [store] , [quantity] , [price] , ISNULL(CAST([quantity]*[price] AS MONEY),0) AS [amount] FROM [stg].[source] OPTION (LABEL = 'CTAS : Partition IN table : Create');Por lo tanto, puede ver que la coherencia de los tipos y el mantenimiento de las propiedades de nulabilidad en una instrucción CTAS es un procedimiento recomendado de ingeniería. Ayuda a mantener la integridad de los cálculos y también garantiza que la modificación de particiones sea posible.
L. Creación de un índice ordenado de almacén de columnas agrupado con MAXDOP 1
CREATE TABLE Table1 WITH (DISTRIBUTION = HASH(c1), CLUSTERED COLUMNSTORE INDEX ORDER(c1) ) AS SELECT * FROM ExampleTable OPTION (MAXDOP 1);Pasos siguientes
- CREATE EXTERNAL DATA SOURCE (Transact-SQL)
- CREATE EXTERNAL FILE FORMAT (Transact-SQL)
- CREATE EXTERNAL TABLE (Transact-SQL)
- CREATE EXTERNAL TABLE AS SELECT (Transact-SQL)
- CREATE TABLE (Azure Synapse Analytics)
- DROP TABLE (Transact-SQL)
- DROP EXTERNAL TABLE (Transact-SQL)
- ALTER TABLE (Transact-SQL)
- ALTER EXTERNAL TABLE (Transact-SQL)
CREATE TABLE AS SELECT (CTAS) es una de las características más importantes de T-SQL disponibles. Se trata de una operación completamente en paralelo que crea una nueva tabla basada en la salida de una instrucción SELECT. CTAS es la forma más sencilla y rápida de crear una copia de una tabla.
Por ejemplo, use CTAS en el almacenamiento de Microsoft Fabric para:
- Crear una copia de una tabla con algunas de las columnas de la tabla de origen.
- Crear una tabla que sea el resultado de una consulta que combina otras tablas.
Para más información sobre el uso de CTAS en el almacén de Microsoft Fabric, consulte Ingesta de datos en el almacén mediante Transact-SQL.
Dado que CTAS se agrega a las funcionalidades para crear tablas, en este tema se procura no repetir el tema CREATE TABLE. En su lugar, se describen las diferencias entre las instrucciones CTAS y CREATE TABLE. Para obtener todos los detalles sobre CREATE TABLE, consulte la instrucción CREATE TABLE.
Sintaxis
CREATE TABLE < database_name.schema_name.table_name | schema_name.table_name | table_name >AS [;] ::= SELECT select_criteriaArgumentos
Opciones de columna
column_name [ . n ]
Los nombres de columna no permiten las opciones de columna mencionadas en CREATE TABLE. En su lugar, puede proporcionar una lista opcional de uno o más nombres de columna para la nueva tabla. Las columnas de la nueva tabla usan los nombres que especifique. Al especificar nombres de columna, el número de columnas de la lista de columnas debe coincidir con el número de columnas de los resultados de selección. Si no especifica nombres de columna, la nueva tabla de destino usa los nombres de columna de los resultados de la instrucción de selección.No se pueden especificar otras opciones de columna, como tipos de datos, intercalación o la nulabilidad. Cada uno de estos atributos se deriva de los resultados de la instrucción SELECT . Aun así, puede usar la instrucción SELECT para cambiar los atributos.
Instrucción SELECT
La instrucción SELECT es la diferencia fundamental entre CTAS y CREATE TABLE.
SELECT select_criteria
Rellena la nueva tabla con los resultados de una instrucción SELECT. select_criteria es el cuerpo de la instrucción SELECT que determina qué datos se copian en la nueva tabla. Para más información sobre las instrucciones SELECT, consulte SELECT (Transact-SQL).
Permisos
CTAS requiere el permiso SELECT en todos los objetos a los que hace referencia en select_criteria.
Para conocer los permisos para crear una tabla, vea Permisos en CREATE TABLE.
Observaciones
Para más información, vea Notas generales en CREATE TABLE.
Limitaciones y restricciones
SET ROWCOUNT (Transact-SQL) no tiene ningún efecto en CTAS. Para lograr un comportamiento similar, use TOP (Transact-SQL).
Para más información, vea Limitaciones y restricciones en CREATE TABLE.
Comportamiento de bloqueo
Para más información, vea Comportamiento de bloqueo en CREATE TABLE.
Ejemplos para copiar una tabla
Para más información sobre el uso de CTAS en el almacén de Microsoft Fabric, consulte Ingesta de datos en el almacén mediante Transact-SQL.
A Usar CTAS para cambiar los atributos de columna
En este ejemplo se usa CTAS para cambiar los tipos de datos y la nulabilidad de varias columnas en la tabla DimCustomer2 .
-- Original table CREATE TABLE [dbo].[DimCustomer2] ( [CustomerKey] INT NOT NULL, [GeographyKey] INT NULL, [CustomerAlternateKey] VARCHAR(15)NOT NULL ) -- CTAS example to change data types and nullability of columns CREATE TABLE test AS SELECT CustomerKey AS CustomerKeyNoChange, CustomerKey*1 AS CustomerKeyChangeNullable, CAST(CustomerKey AS DECIMAL(10,2)) AS CustomerKeyChangeDataTypeNullable, ISNULL(CAST(CustomerKey AS DECIMAL(10,2)),0) AS CustomerKeyChangeDataTypeNotNullable, GeographyKey AS GeographyKeyNoChange, ISNULL(GeographyKey,0) AS GeographyKeyChangeNotNullable, CustomerAlternateKey AS CustomerAlternateKeyNoChange, CASE WHEN CustomerAlternateKey = CustomerAlternateKey THEN CustomerAlternateKey END AS CustomerAlternateKeyNullable, FROM [dbo].[DimCustomer2] -- Resulting table CREATE TABLE [dbo].[test] ( [CustomerKeyNoChange] INT NOT NULL, [CustomerKeyChangeNullable] INT NULL, [CustomerKeyChangeDataTypeNullable] DECIMAL(10, 2) NULL, [CustomerKeyChangeDataTypeNotNullable] DECIMAL(10, 2) NOT NULL, [GeographyKeyNoChange] INT NULL, [GeographyKeyChangeNotNullable] INT NOT NULL, [CustomerAlternateKeyNoChange] VARCHAR(15) NOT NULL, [CustomerAlternateKeyNullable] VARCHAR(15) NULL, NOT NULL )B. Usar CTAS para crear una tabla con menos columnas
En el ejemplo siguiente se crea una tabla denominada myTable (c, ln) . La nueva tabla solo tiene dos columnas. Usa los alias de columna en la instrucción SELECT para los nombres de las columnas.
CREATE TABLE myTable AS SELECT CustomerKey AS c, LastName AS ln FROM dimCustomer;C. Usar CTAS en lugar de SELECT..EN
El código de SQL Server suele usar SELECT..INTO para rellenar una tabla con los resultados de una instrucción SELECT. Este es un ejemplo de una instrucción SELECT..INTO de SQL Server.
SELECT * INTO NewFactTable FROM [dbo].[FactInternetSales]En este ejemplo se muestra cómo reescribir la anterior instrucción SELECT..INTO como una instrucción CTAS.
CREATE TABLE NewFactTable AS SELECT * FROM [dbo].[FactInternetSales] ;D. Usar CTAS para simplificar las instrucciones de fusión
Las instrucciones de fusión se pueden sustituir, al menos en parte, mediante CTAS . Es posible consolidar INSERT y UPDATE en una única instrucción. Los registros eliminados deben cerrarse en una segunda instrucción.
A continuación se muestra un ejemplo de UPSERT :
CREATE TABLE dbo.[DimProduct_upsert] AS -- New rows and new versions of rows SELECT s.[ProductKey] , s.[EnglishProductName] , s.[Color] FROM dbo.[stg_DimProduct] AS s UNION ALL -- Keep rows that are not being touched SELECT p.[ProductKey] , p.[EnglishProductName] , p.[Color] FROM dbo.[DimProduct] AS p WHERE NOT EXISTS ( SELECT * FROM [dbo].[stg_DimProduct] s WHERE s.[ProductKey] = p.[ProductKey] ) ;E. establezca explícitamente el tipo de datos y la nulabilidad de salida
Al migrar código de SQL Server al almacenamiento, puede encontrarse con este tipo de patrón de codificación:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 CREATE TABLE result (result DECIMAL(7,2) NOT NULL) INSERT INTO result SELECT @d*@f ;Instintivamente pensará que debe migrar este código a una instrucción CTAS, y tendría razón. Sin embargo, existe un problema oculto aquí.
El código siguiente NO produce el mismo resultado:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 ; CREATE TABLE ctas_r AS SELECT @d*@f as result ;Observe que la columna «result» traslada el tipo de datos y los valores de nulabilidad de la expresión. Esto puede provocar sutiles variaciones en los valores si no tiene cuidado.
Pruebe por ejemplo lo siguiente:
SELECT result,result*@d from result ; SELECT result,result*@d from ctas_r ;El valor almacenado para el resultado es diferente. Dado que el valor almacenado en la columna de resultados se usa en otras expresiones, el error es todavía mayor.

Esto es importante para las migraciones de datos. Aunque se puede decir que la segunda consulta es más precisa, hay un problema. Los datos serían diferentes en comparación con el sistema de origen, lo que produce problemas de integridad en la migración. Este es uno de los pocos casos en los que la respuesta «incorrecta» es en realidad la correcta.
El motivo por el que vemos esta discrepancia entre los dos resultados se debe a la conversión de tipos implícita. En el primer ejemplo, la tabla define la definición de columna. Cuando se inserta la fila, se realiza una conversión de tipos implícita. En el segundo ejemplo no hay ninguna conversión de tipos implícita, ya que la expresión define el tipo de datos de la columna. Observe también que la columna del segundo ejemplo se ha definido como una columna que acepta valores NULL mientras que en el primer ejemplo no. Al crear la tabla en el primer ejemplo, se definió explícitamente la nulabilidad de la columna. En el segundo ejemplo, esto le correspondía a la expresión, lo que conllevaba una definición NULL de forma predeterminada.
Para resolver estos problemas, debe establecer explícitamente la conversión de tipos y la nulabilidad en la parte SELECT de la instrucción CTAS . No puede establecer estas propiedades en la parte de creación de la tabla.
En este ejemplo se muestra cómo corregir el código:
DECLARE @d DECIMAL(7,2) = 85.455 , @f FLOAT(24) = 85.455 CREATE TABLE ctas_r AS SELECT ISNULL(CAST(@d*@f AS DECIMAL(7,2)),0) as resultTenga en cuenta lo siguiente en el ejemplo:
- Podían haberse usado CAST o CONVERT.
- Se usa ISNULL para forzar la nulabilidad, no COALESCE.
- ISNULL es la función más externa.
- La segunda parte de ISNULL es una constante, es decir, 0 .
Para que la nulabilidad se establezca correctamente, es fundamental usar ISNULL , no COALESCE . COALESCE no es una función determinista, por lo que el resultado de la expresión siempre aceptará valores NULL. ISNULL es diferente, ya que es determinista. Por lo tanto, cuando la segunda parte de la función ISNULL es una constante o un literal, el valor resultante será NOT NULL.
Esta sugerencia no solo es útil para garantizar la integridad de los cálculos, sino que también es importante para la modificación de particiones de tabla. Imagine que ha definido como hecho esta tabla:
CREATE TABLE [dbo].[Sales] ( [date] INT NOT NULL , [product] INT NOT NULL , [store] INT NOT NULL , [quantity] INT NOT NULL , [price] DECIMAL(7,2) NOT NULL , [amount] DECIMAL(7,2) NOT NULL ) ;Pero el campo de valor es una expresión calculada, no forma parte del origen de datos.
Por lo tanto, puede ver que la coherencia de los tipos y el mantenimiento de las propiedades de nulabilidad en una instrucción CTAS es un procedimiento recomendado de ingeniería. Ayuda a mantener la integridad en los cálculos.
Pasos siguientes
- Creación de tablas en el almacenamiento de Microsoft Fabric
- ¿Qué es el almacenamiento de datos en Microsoft Fabric?
- Ingesta de datos en el almacén mediante Transact-SQL
Мультимодельные СУБД — основа современных информационных систем?
Современные информационные системы достаточно сложны. Не в последнюю очередь их сложность обусловлена сложностью обрабатываемых в них данных. Сложность же данных зачастую заключается в многообразии используемых моделей данных. Так, например, когда данные становятся «большими», одной из доставляющих неудобства характеристик считается не только их объем («volume»), но и их разнообразие («variety»).
Если вы пока не находите изъяна в рассуждениях, то читайте дальше.

Содержание статьи
Polyglot persistence
Сказанное выше приводит к тому, что порою в рамках даже одной системы приходится для хранения данных и решения различных задач по их обработке использовать несколько различных СУБД, каждая из которых поддерживает свою модель данных. С легкой руки М. Фаулера, автора ряда известных книг и одного из соавторов Agile Manifesto, такая ситуация получила название многовариантного хранения («polyglot persistence»).
Фаулеру принадлежит и следующий пример организации хранения данных в полнофункциональном и высоконагруженном приложении в сфере электронной коммерции.

Пример этот, конечно, несколько утрированный, но некоторые соображения в пользу выбора той или иной СУБД для соответствующей цели можно найти, например, здесь.
Понятно, что быть служителем в таком зоопарке нелегко.
- Объем кода, выполняющего сохранение данных, растет пропорционально числу используемых СУБД; объем кода, синхронизирующего данные, — хорошо если не пропорционально квадрату этого числа.
- Кратно числу используемых СУБД возрастают затраты на обеспечение enterprise-характеристик (масштабируемости, отказоустойчивости, высокой доступности) каждой из используемых СУБД.
- Невозможно обеспечить enterprise-характеристики подсистемы хранения в целом — особенно транзакционность.
С точки зрения директора зоопарка все выглядит так:
- Кратное увеличение стоимости лицензий и техподдержки от производителя СУБД.
- Раздутие штата и увеличение сроков.
- Прямые финансовые потери или штрафные санкции из-за несогласованности данных.
Имеет место значительный рост совокупной стоимости владения системой (TCO). Есть ли из ситуации «многовариантного хранения» какой-то выход?
Мультимодельность
Термин «многовариантное хранение» вошел в обиход в 2011 году. Осознание проблем подхода и поиск решения заняли несколько лет, и к 2015 году устами аналитиков Gartner ответ был сформулирован:
Будущее СУБД, их архитектур и способов использования — мультимодельность.
Ведущие операционные СУБД будут предлагать несколько моделей — реляционную и нереляционные — в составе единой платформы.
Похоже, что в этот раз аналитики Gartner с прогнозом не ошиблись. Если зайти на страницу с основным рейтингом СУБД на DB-Engines, можно увидеть, что большая часть его лидеров позиционирует себя именно как мультимодельные СУБД. То же можно увидеть и на странице с любым частным рейтингом.
В таблице ниже приведены СУБД — лидеры в каждом из частных рейтингов, заявляющие о своей мультимодельности. Для каждой СУБД указаны первоначальная поддерживаемая модель (когда-то бывшая единственной) и наряду с ней модели, поддерживаемые сейчас. Также приведены СУБД, позиционирующие себя как «изначально мультимодельные», не имеющие по заявлениям создателей какой-либо первоначальной унаследованной модели.
СУБД Изначальная модель Дополнительные модели Oracle Реляционная Графовая, документная MS SQL Реляционная Графовая, документная PostgreSQL Реляционная Графовая*, документная MarkLogic Документная Графовая, реляционная MongoDB Документная Ключ-значение, графовая* DataStax Wide-column Документная, графовая Redis Ключ-значение Документная, графовая* ArangoDB — Графовая, документная OrientDB — Графовая, документная Azure CosmosDB — Графовая, документная, реляционная Примечания к таблице
Звездочками в таблице помечены утверждения, требующие оговорок:
- СУБД PostgreSQL не поддерживает графовую модель данных, однако ее поддерживает такой продукт на ее основе, как, например, AgensGraph.
- Применительно к MongoDB правильнее говорить скорее о наличии графовых операторов в языке запросов ( $lookup , $graphLookup ), чем о поддержке графовой модели, хотя, конечно, их введение потребовало некоторых оптимизаций на уровне физического хранения в направлении поддержки графовой модели.
- Применительно к Redis имеется в виду расширение RedisGraph.
Далее для каждого из классов мы покажем, как реализуется поддержка нескольких моделей в СУБД из этого класса. Наиболее важными будем считать реляционную, документную и графовую модели и на примерах конкретных СУБД показывать, как реализуются «недостающие».
Мультимодельные СУБД на основе реляционной модели
Ведущими СУБД в настоящее время являются реляционные, прогноз Gartner нельзя было бы считать сбывшимся, если бы РСУБД не демонстрировали движения в направлении мультимодельности. И они демонстрируют. Теперь соображения о том, что мультимодельная СУБД подобна швейцарскому ножу, которым ничего нельзя сделать хорошо, можно направлять сразу Ларри Эллисону.
Автору, однако, больше нравится реализация мультимодельности в Microsoft SQL Server, на примере которого поддержка РСУБД документной и графовой моделей и будет описана.
Документная модель в MS SQL Server
О том, как в MS SQL Server реализована поддержка документной модели, на Хабре уже было две отличных статьи, ограничусь кратким пересказом и комментарием:
- Работаем с JSON в SQL Server 2016
- SQL Server 2017 JSON
Способ поддержки документной модели в MS SQL Server достаточно типичен для реляционных СУБД: JSON-документы предлагается хранить в обычных текстовых полях. Поддержка документной модели заключается в предоставлении специальных операторов для разбора этого JSON:
- JSON_VALUE для извлечения скалярных значений атрибутов,
- JSON_QUERY для извлечения поддокументов.
Вторым аргументом обоих операторов является выражение в JSONPath-подобном синтаксисе.
Абстрактно можно сказать, что хранимые таким образом документы не являются в реляционной СУБД «сущностями первого класса», в отличие от кортежей. Конкретно в MS SQL Server в настоящее время отсутствуют индексы по полям JSON-документов, что делает затруднительными операции соединения таблиц по значениям этих полей и даже выборку документов по этим значениям. Впрочем, возможно создать по такому полю вычислимый столбец и индекс по нему.
Дополнительно MS SQL Server предоставляет возможность удобно конструировать JSON-документ из содержимого таблиц с помощью оператора FOR JSON PATH — возможность, в известном смысле противоположную предыдущей, обычному хранению. Понятно, что какой бы быстрой ни была РСУБД, такой подход противоречит идеологии документных СУБД, по сути хранящих готовые ответы на популярные запросы, и может решать лишь проблемы удобства разработки, но не быстродействия.
Наконец, MS SQL Server позволяет решать задачу, обратную конструированию документа: можно разложить JSON по таблицам с помощью OPENJSON . Если документ не совсем плоский, потребуется использовать CROSS APPLY .
Графовая модель в MS SQL Server
Поддержка графовой ( LPG ) модели реализована в Microsoft SQL Server тоже вполне предсказуемо: предлагается использовать специальные таблицы для хранения узлов и для хранения ребер графа. Такие таблицы создаются с использованием выражений CREATE TABLE AS NODE и CREATE TABLE AS EDGE соответственно.
Таблицы первого вида сходны с обычными таблицами для хранения записей с тем лишь внешним отличием, что в таблице присутствует системное поле $node_id — уникальный в пределах базы данных идентификатор узла графа.
Аналогично, таблицы второго вида имеют системные поля $from_id и $to_id , записи в таких таблицах понятным образом задают связи между узлами. Для хранения связей каждого вида используется отдельная таблица.

Проиллюстрируем сказанное примером. Пусть графовые данные имеют схему как на приведенном рисунке. Тогда для создания соответствующей структуры в базе данных нужно выполнить следующие DDL-запросы:
CREATE TABLE Person ( ID INTEGER NOT NULL, name VARCHAR(100) ) AS NODE; CREATE TABLE Cafe ( ID INTEGER NOT NULL, name VARCHAR(100), ) AS NODE; CREATE TABLE likes ( rating INTEGER ) AS EDGE; CREATE TABLE friendOf AS EDGE; /* Возможно в SQL Server 2019: ALTER TABLE likes ADD CONSTRAINT EC_LIKES CONNECTION (Person TO Cafe); */Основная специфика таких таблиц заключается в том, что в запросах к ним возможно использовать графовые паттерны с Cypher-подобным синтаксисом (впрочем, « * » и пр. пока не поддерживаются). Также на основе измерений производительности можно предположить, что способ хранения данных в этих таблицах отличен от механизма хранения данных в обычных таблицах и оптимизирован для выполнения подобных графовых запросов.
SELECT Cafe.name FROM Person, likes, Cafe WHERE MATCH (Person-(friendOf)-(likes)->Cafe) AND Person.name = 'John';Более того, довольно трудно при работе с такими таблицами эти графовые паттерны не использовать, поскольку в обычных SQL-запросах для решения аналогичных задач потребуется предпринимать дополнительные усилия для получения системных «графовых» идентификаторов узлов ( $node_id , $from_id , $to_id ; по этой же причине запросы на вставку данных не приведены здесь как слишком громоздкие).
Подводя итог описанию реализаций документной и графовой моделей в MS SQL Server, я бы отметил, что подобные реализации одной модели поверх другой не кажутся удачными в первую очередь с точки зрения языкового дизайна. Требуется расширять один язык другим, языки не вполне «ортогональны», правила сочетаемости могут быть довольно причудливы.
Мультимодельные СУБД на основе документной модели
В этом разделе хочется проиллюстрировать реализацию мультимодельности в документных СУБД на примере не наиболее популярной из них MongoDB (как было сказано, в ней есть лишь условно графовые операторы $lookup и $graphLookup , не работающие на шардированных коллекциях), а на примере более зрелой и «энтерпрайзной» СУБД MarkLogic.
Итак, пусть коллекция содержит набор XML-документов следующего вида (хранить JSON-документы MarkLogic тоже позволяет):
John Smith Реляционная модель в MarkLogic
Реляционное представление коллекции документов можно создать с помощью шаблона отображения (содержимым элементов value в примере ниже может быть произвольный XPath):
/Person Person SSN @SSN string name name surname surname К созданному представлению можно адресовать SQL-запрос (например, через ODBC):
SELECT name, surname FROM Person WHERE name="John"К сожалению, созданное с помощью шаблона отображения реляционное представление доступно только для чтения. При обработке запроса к нему MarkLogic попытается использовать документные индексы. Прежде в MarkLogic были и ограниченные реляционные представления, целиком основанные на индексах и доступные на запись, но сейчас они считаются deprecated.
Графовая модель в MarkLogic
С поддержкой графовой ( RDF ) модели все обстоит примерно так же. Опять-таки с помощью шаблона отображения можно создать RDF-представление коллекции документов из примера выше:
/Person PREFIX "http://example.org/example#" sem:iri( $PREFIX || @SSN ) sem:iri( $PREFIX || surname ) sem:iri( $PREFIX || @SSN ) sem:iri( $PREFIX || name ) К полученному RDF-графу можно адресовать SPARQL-запрос:
PREFIX : SELECT ?name ?surname
В отличие от реляционной, графовую модель MarkLogic поддерживает еще двумя другими способами:
- СУБД может быть полноценным отдельным хранилищем RDF-данных (триплеты в нем будут называться managed в противоположность описанным выше extracted).
- RDF в специальной сериализации может быть попросту вставлен в XML- или JSON-документы (и триплеты тогда будут называться unmanaged). Вероятно, это такая альтернатива механизмам idref и пр.
Хорошее представление о том, как «на самом деле» все устроено в MarkLogic, дает Optic API, в этом смысле оно низкоуровневое, хотя назначение его скорее обратное — попробовать абстрагироваться от используемой модели данных, обеспечить согласованную работу с данными в различных моделях, транзакционность и пр.
Мультимодельные СУБД «без основной модели»
На рынке также представлены СУБД, позиционирующие себя как изначально мультимодельные, не имеющие никакой унаследованной основной модели. К их числу относятся ArangoDB, OrientDB (c 2018 года компания-разработчик принадлежит SAP) и CosmosDB (сервис в составе облачной платформы Microsoft Azure).
На самом деле «основные» модели в ArangoDB и OrientDB есть. Это в том и в другом случае собственные модели данных, являющиеся обобщениями документной. Обобщения заключаются в основном в облегчении возможности производить запросы графового и реляционного характера.
Эти модели являются в указанных СУБД единственно доступными для использования, для работы с ними предназначены собственные языки запросов. Безусловно, такие модели и СУБД перспективны, однако отсутствие совместимости со стандартными моделями и языками делает невозможным использование этих СУБД в унаследованных системах — замену ими уже используемых там СУБД.
Про ArangoDB и OrientDB на Хабре уже была замечательная статья: JOIN в NoSQL базах данных.
ArangoDB
ArangoDB заявляет поддержку графовой модели данных.
Узлы графа в ArangoDB — это обычные документы, а ребра — документы специального вида, имеющие наряду с обычными системными полями ( _key , _id , _rev ) системные поля _from и _to . Документы в документных СУБД традиционно объединяются в коллекции. Коллекции документов, представляющих ребра, в ArangoDB называются edge-коллекциями. К слову, документы edge-коллекций — это тоже документы, поэтому ребра в ArangoDB могут выступать также и узлами.
Исходные данные
Пусть у нас есть коллекция persons , документы которой выглядят так:
Пусть также есть коллекция cafes :
Тогда коллекция likes может выглядеть следующим образом:
Запросы и результаты
Запрос в графовом стиле на используемом в ArangoDB языке AQL, возвращающий в человекочитаемом виде сведения о том, кому какое кафе нравится, выглядит так:
FOR p IN persons FOR c IN OUTBOUND p likes RETURN
В реляционном стиле, когда мы скорее «вычисляем» связи, а не храним их, этот запрос можно переписать так (к слову, без коллекции likes можно было бы обойтись):
FOR p IN persons FOR l IN likes FILTER p._key == l._from FOR c IN cafes FILTER l._to == c._key RETURN
Результат в обоих случаях будет один и тот же:
Еще запросы и результаты
Если кажется, что формат результата выше характерен больше для реляционной СУБД, чем для документной, можно попробовать такой запрос (либо можно воспользоваться COLLECT ):
FOR p IN persons RETURN
Результат будет иметь следующий вид:
OrientDB
В основе реализации графовой модели поверх документной в OrientDB лежит возможность полей документов иметь помимо более-менее стандартных скалярных значений еще и значения таких типов, как LINK , LINKLIST , LINKSET , LINKMAP и LINKBAG . Значения этих типов — ссылки или коллекции ссылок на системные идентификаторы документов.
Присваиваемый системой идентификатор документа имеет «физический смысл», указывая позицию записи в базе, и выглядит примерно так: @rid : #3:16 . Тем самым значения ссылочных свойств — действительно скорее указатели (как в графовой модели), а не условия отбора (как в реляционной).
Как и в ArangoDB, в OrientDB ребра представляются отдельными документами (хотя если у ребра нет своих свойств, его можно сделать легковесным, и ему не будет соответствовать отдельный документ).
Исходные данные
В формате, приближенном к формату дампа базы OrientDB, данные из предыдущего примера для ArangoDB выглядели бы примерно так:
Как мы видим, вершины тоже хранят сведения о входящих и исходящих ребрах. При использовании Document API за ссылочной целостностью приходится следить самому, а Graph API берет эту работу на себя. Но посмотрим, как выглядят обращение к OrientDB на «чистых», не интегрированных в языки программирования, языках запросов.
Запросы и результаты
Запрос, аналогичный по назначению запросу из примера для ArangoDB, в OrientDB выглядит так:
SELECT name AS person_name, OUT('likes').name AS cafe_name FROM Person UNWIND cafe_nameРезультат будет получен в следующем виде:
Если формат результата опять кажется чересчур «реляционным», нужно убрать строку с UNWIND() :
Язык запросов OrientDB можно охарактеризовать как SQL c Gremlin-подобными вставками. В версии 2.2 появилась Cypher-подобная форма запроса, MATCH :
MATCH -likes-> RETURN person.name AS person_name, LIST(cafe.name) AS cafe_name GROUP BY person_nameФормат результата будет таким же, как в предыдущем запросе. Подумайте, что нужно убрать, чтобы сделать его более «реляционным», как в самом первом запросе.
Azure CosmosDB
В меньшей степени сказанное выше об ArangoDB и OrientDB относится к Azure CosmosDB. CosmosDB предоставляет следующие API доступа к данным: SQL, MongoDB, Gremlin и Cassandra.
SQL API и MongoDB API используются для доступа к данным в документной модели. Gremlin API и Cassandra API — для доступа к данным соответственно в графовой и колоночной. Данные во всех моделях сохраняются в формате внутренней модели CosmosDB: ARS («atom-record-sequence»), которая также близка к документной.

Но выбранная пользователем модель данных и используемый API фиксируются в момент создания аккаунта в сервисе. Невозможно получить доступ к данным, загруженным в одной модели, в формате другой модели, что иллюстрировалось бы примерно таким рисунком:

Тем самым мультимодельность в Azure CosmosDB на сегодняшний день представляет собой лишь возможность использовать несколько баз данных, поддерживающих различные модели, от одного производителя, что не решает всех проблем многовариантного хранения.
Мультимодельные СУБД на основе графовой модели?
Обращает на себя внимание тот факт, что на рынке пока нет мультимодельных СУБД, имеющих в основе графовую модель (если не считать мультимодельностью поддержку одновременно двух графовых моделей: RDF и LPG; см. об этом в предыдущей публикации). Наибольшие затруднений вызывает реализация поверх графовой модели документной, а не реляционной.
Вопрос о том, как реализовать поверх графовой модели реляционную, рассматривался еще во времена становления этой последней. Как говорил, например, Дэвид Макговерен:
There is nothing inherent in the graph approach that prevents creating a layer (e.g., by suitable indexing) on a graph database that enables a relational view with (1) recovery of tuples from the usual key value pairs and (2) grouping of tuples by relation type.
При реализации же документной модели поверх графовой нужно иметь в виду, например, следующее:
- Элементы JSON-массива считаются упорядоченными, исходящие из вершины ребра графа — нет;
- Данные в документной модели обычно денормализованы, хранить несколько копий одного и того же вложенного документа все же не хочется, а идентификаторов у поддокументов обычно нет;
- С другой стороны, идеология документных СУБД в том и заключается, что документы являются готовыми «агрегатами», которые не нужно каждый раз строить заново. Требуется обеспечить в графовой модели возможность быстро получить подграф, соответствующий готовому документу.
Немного рекламы
Автор статьи имеет отношение к разработке СУБД NitrosBase, внутренняя модель которой является графовой, а внешние модели — реляционная и документная — являются её представлениями. Все модели равноправны: практически любые данные доступны в любой из них с использованием естественного для неё языка запросов. Более того, в любом представлении данные могут быть изменены. Изменения отразятся во внутренней модели и, соответственно, в других представлениях.
Как выглядит соответствие моделей в NitrosBase — опишу, надеюсь, в одной из следующих статей.
Заключение
Надеюсь, что общие контуры того, что называется мультимодельностью, стали читателю более-менее ясны. Мультимодельными называются достаточно разные СУБД, и «поддержка нескольких моделей» может выглядеть по-разному. Для понимания того, что называют «мультимодельностью» в каждом конкретном случае, полезно ответить на следующие вопросы:
- Идет ли речь о поддержке традиционных моделей или же о некоей одной гибридной модели?
- «Равноправны» ли модели, или одна из них является подлежащей для других?
- «Безразличны» ли модели друг другу? Могут ли данные, записанные в одной модели, быть прочитанными в другой или даже перезаписаны?
Думаю, на вопрос об актуальности мультимодельных СУБД уже можно дать положительный ответ, но интересен вопрос о том, какие именно их разновидности будут более востребованы в ближайшее время. Похоже, более востребованы будут мультимодельные СУБД, поддерживающие традиционные модели, в первую очередь, реляционную; популярность же мультимодельных СУБД, предлагающих новые модели, сочетающие в себе достоинства различных традиционных, — дело более отдаленного будущего.
Инструкция CREATE TABLE (Transact-SQL)
Создает новую таблицу в SQL Server и База данных SQL Azure.
Синтаксис Azure Synapse Analytics см. в статье CREATE TABLE (Azure Synapse Analytics).
Параметры синтаксиса
Общий синтаксис
Простой синтаксис CREATE TABLE (общий, если не используются параметры):
CREATE TABLE < database_name.schema_name.table_name | schema_name.table_name | table_name >( < > [ . n ] ) [ ; ]Полный синтаксис
Синтаксис CREATE TABLE на основе диска:
CREATE TABLE < database_name.schema_name.table_name | schema_name.table_name | table_name >[ AS FileTable ] ( < | | | [ ] [ . n ] | [ ] > [ . n ] [ PERIOD FOR SYSTEM_TIME ( system_start_time_column_name , system_end_time_column_name ) ] ) [ ON < partition_scheme_name ( partition_column_name ) | filegroup | "default" >] [ TEXTIMAGE_ON < filegroup | "default" >] [ FILESTREAM_ON < partition_scheme_name | filegroup | "default" >] [ WITH ( [ . n ] ) ] [ ; ] ::= column_name [ FILESTREAM ] [ COLLATE collation_name ] [ SPARSE ] [ MASKED WITH ( FUNCTION = 'mask_function' ) ] [ [ CONSTRAINT constraint_name ] DEFAULT constant_expression ] [ IDENTITY [ ( seed , increment ) ] [ NOT FOR REPLICATION ] [ GENERATED ALWAYS AS < ROW | TRANSACTION_ID | SEQUENCE_NUMBER > < START | END >[ HIDDEN ] ] [ [ CONSTRAINT constraint_name ] ] [ ROWGUIDCOL ] [ ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = key_name , ENCRYPTION_TYPE = < DETERMINISTIC | RANDOMIZED >, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ) ] [ [ . n ] ] [ ] ::= [ type_schema_name. ] type_name [ ( precision [ , scale ] | max | [ < CONTENT | DOCUMENT >] xml_schema_collection ) ] ::= [ CONSTRAINT constraint_name ] < < PRIMARY KEY | UNIQUE >[ CLUSTERED | NONCLUSTERED ] [ ( [ . n ] ) ] [ WITH FILLFACTOR = fillfactor | WITH ( [ . 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 ) > ::= INDEX index_name [ CLUSTERED | NONCLUSTERED ] [ WITH ( [ . n ] ) ] [ ON < partition_scheme_name ( column_name ) | filegroup_name | default >] [ FILESTREAM_ON < filestream_filegroup_name | partition_scheme_name | "NULL" >] ::= column_name AS computed_column_expression [ PERSISTED [ NOT NULL ] ] [ [ CONSTRAINT constraint_name ] < PRIMARY KEY | UNIQUE >[ CLUSTERED | NONCLUSTERED ] [ WITH FILLFACTOR = fillfactor | WITH ( [ . 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 ) ] ::= column_set_name XML COLUMN_SET FOR ALL_SPARSE_COLUMNS ::= [ CONSTRAINT constraint_name ] < < PRIMARY KEY | UNIQUE >[ CLUSTERED | NONCLUSTERED ] ( column_name [ ASC | DESC ] [ . n ] ) [ WITH FILLFACTOR = fillfactor | WITH ( [ . n ] ) ] [ ON < partition_scheme_name (partition_column_name) | filegroup | "default" >] | FOREIGN KEY ( column_name [ . 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 index_name [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] ( column_name [ ASC | DESC ] [ . n ] ) | INDEX index_name CLUSTERED COLUMNSTORE | INDEX index_name [ NONCLUSTERED ] COLUMNSTORE ( column_name [ . n ] ) >[ INCLUDE ( column_name [ . n ] ) ] [ WHERE ] [ WITH ( [ . n ] ) ] [ ON < partition_scheme_name ( column_name ) | filegroup_name | default >] [ FILESTREAM_ON < filestream_filegroup_name | partition_scheme_name | "NULL" >] > ::= < [ DATA_COMPRESSION = < NONE | ROW | PAGE >[ ON PARTITIONS ( < | > [ . n ] ) ] ] [ XML_COMPRESSION = < ON | OFF >[ ON PARTITIONS ( < | > [ . n ] ) ] ] [ FILETABLE_DIRECTORY = ] [ FILETABLE_COLLATE_FILENAME = < | database_default > ] [ FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME = ] [ FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME = ] [ FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME = ] [ SYSTEM_VERSIONING = ON [ ( HISTORY_TABLE = schema_name.history_table_name [ , DATA_CONSISTENCY_CHECK = < ON | OFF >] ) ] ] [ REMOTE_DATA_ARCHIVE = < ON [ ( [ . n] ) ] | OFF ( MIGRATION_STATE = PAUSED ) > ] [ DATA_DELETION = ON < ( FILTER_COLUMN = column_name, RETENTION_PERIOD = < INFINITE | number < DAY | DAYS | WEEK | WEEKS | MONTH | MONTHS | YEAR | YEARS >) > ] [ LEDGER = ON [ ( [ . n ] ) ] | OFF ] > ::= < [ LEDGER_VIEW = schema_name.ledger_view_name [ ( [ . n ] ) ] [ APPEND_ONLY = ON | OFF ] > ::= < [ TRANSACTION_ID_COLUMN_NAME = transaction_id_column_name ] [ SEQUENCE_NUMBER_COLUMN_NAME = sequence_number_column_name ] [ OPERATION_TYPE_COLUMN_NAME = operation_type_id column_name ] [ OPERATION_TYPE_DESC_COLUMN_NAME = operation_type_desc_column_name ] > ::= < [ FILTER_PREDICATE = < NULL | table_predicate_function >, ] MIGRATION_STATE = < OUTBOUND | INBOUND | PAUSED >> ::= < PAD_INDEX = < ON | OFF >| FILLFACTOR = fillfactor | IGNORE_DUP_KEY = < ON | OFF >| STATISTICS_NORECOMPUTE = < ON | OFF >| STATISTICS_INCREMENTAL = < ON | OFF >| ALLOW_ROW_LOCKS = < ON | OFF >| ALLOW_PAGE_LOCKS = < ON | OFF >| OPTIMIZE_FOR_SEQUENTIAL_KEY = < ON | OFF >| COMPRESSION_DELAY = < 0 | delay [ Minutes ] >| DATA_COMPRESSION = < NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE >[ ON PARTITIONS ( < partition_number_expression | > [ . n ] ) ] | XML_COMPRESSION = < ON | OFF >[ ON PARTITIONS ( < | > [ . n ] ) ] ] > ::= TO
Синтаксис для таблиц, оптимизированных для памяти
Синтаксис CREATE TABLE, оптимизированный для памяти:
CREATE TABLE < database_name.schema_name.table_name | schema_name.table_name | table_name >( < | [ ] [ . n ] | [ ] [ . n ] > [ PERIOD FOR SYSTEM_TIME ( system_start_time_column_name , system_end_time_column_name ) ] ) [ WITH ( [ . n ] ) ] [ ; ] ::= column_name [ COLLATE collation_name ] [ GENERATED ALWAYS AS ROW < START | END >[ HIDDEN ] ] [ NULL | NOT NULL ] [ [ CONSTRAINT constraint_name ] DEFAULT memory_optimized_constant_expression ] | [ IDENTITY [ ( 1, 1 ) ] ] [ ] [ ] ::= [type_schema_name. ] type_name [ (precision [ , scale ]) ] ::= [ CONSTRAINT constraint_name ] < < PRIMARY KEY | UNIQUE > < NONCLUSTERED | NONCLUSTERED HASH WITH ( BUCKET_COUNT = bucket_count ) >[ ( [ . n ] ) ] | [ FOREIGN KEY ] REFERENCES [ schema_name. ] referenced_table_name [ ( ref_column ) ] | CHECK ( logical_expression ) > ::= [ CONSTRAINT constraint_name ] < < PRIMARY KEY | UNIQUE > < NONCLUSTERED ( column_name [ ASC | DESC ] [ . n ]) | NONCLUSTERED HASH ( column_name [ . n ] ) WITH ( BUCKET_COUNT = bucket_count ) >| FOREIGN KEY ( column_name [ . n ] ) REFERENCES referenced_table_name [ ( ref_column [ . n ] ) ] | CHECK ( logical_expression ) > ::= INDEX index_name < [ NONCLUSTERED ] | [ NONCLUSTERED ] HASH WITH ( BUCKET_COUNT = bucket_count ) > ::= INDEX index_name < [ NONCLUSTERED ] HASH ( column_name [ . n ] ) WITH ( BUCKET_COUNT = bucket_count ) | [ NONCLUSTERED ] ( column_name [ ASC | DESC ] [ . n ] ) [ ON filegroup_name | default ] | CLUSTERED COLUMNSTORE [ WITH ( COMPRESSION_DELAY = < 0 | delay [ Minutes ] >) ] [ ON filegroup_name | default ] > ::= < MEMORY_OPTIMIZED = ON | DURABILITY = < SCHEMA_ONLY | SCHEMA_AND_DATA >| SYSTEM_VERSIONING = ON [ ( HISTORY_TABLE = schema_name.history_table_name [, DATA_CONSISTENCY_CHECK = < ON | OFF >] ) ] >Сведения о синтаксисе Transact-SQL для SQL Server 2014 (12.x) и более ранних версиях см . в документации по предыдущим версиям.
Аргументы
database_name
Имя базы данных, в которой создается таблица. Параметр database_name должен указывать имя существующей базы данных. Если не указано, в качестве database_name по умолчанию выбирается текущая база данных. Имя входа для текущего соединения должно быть связано с идентификатором пользователя, существующего в базе данных, указанной аргументом database_name, а этот пользователь должен обладать разрешениями CREATE TABLE.
schema_name
Имя схемы, которой принадлежит новая таблица.
table_name
Имя новой таблицы. Имена таблиц должны соответствовать правилам для идентификаторов. Аргумент table_name может состоять не более чем из 128 символов, за исключением имен локальных временных таблиц (имена с префиксом из одного символа решетки ( # )), длина которых не должна превышать 116 символов.
AS FileTable
Область применения: SQL Server 2012 (11.x) и более поздних версий.
Создает новую таблицу FileTable. Нет необходимости указывать столбцы, так как таблица FileTable имеет фиксированное схему. Дополнительные сведения см. в статье Таблицы FileTable.
column_name AS computed_column_expression
Выражение, определяющее значение вычисляемого столбца. Вычисляемый столбец представляет собой виртуальный столбец, физически не хранящийся в таблице, если для него не установлен признак PERSISTED. Значение столбца вычисляется на основе выражения, использующего другие столбцы той же таблицы. Например, определение вычисляемого столбца может быть следующим: cost AS price * qty . Выражение может быть именем невычисляемого столбца, константой, функцией, переменной или любой их комбинацией, соединенной одним или несколькими операторами. Выражение не может быть вложенным запросом или содержать псевдонимы типов данных.
Вычисляемые столбцы могут использоваться в списках выбора, предложениях WHERE, ORDER BY и в любых других местах, в которых могут использоваться обычные выражения, за исключением следующих случаев.
- Для использования в ограничениях FOREIGN KEY или CHECK вычисляемые столбцы должны быть помечены как PERSISTED.
- Вычисляемый столбец может использоваться в качестве ключевого столбца в индексе или в качестве компонента какого-либо ограничения PRIMARY KEY или UNIQUE, если значение этого вычисляемого столбца определено детерминистическим выражением, а тип данных результата разрешен в столбцах индекса. Например, если таблица содержит целочисленные столбцы a и b , вычисляемый столбец a + b может быть включен в индекс, а вычисляемый столбец a + DATEPART(dd, GETDATE()) — не может, так как его значение может изменяться при последующих вызовах.
- Вычисляемый столбец не может быть целевым столбцом инструкций INSERT или UPDATE.
Каждая строка таблицы может содержать различные значения столбцов, задействованных в вычисляемом столбце; таким образом, значение вычисляемого столбца не будет одним и тем же в каждой строке.
В зависимости от используемых выражений значение NULL вычисляемых столбцов определяется автоматически ядро СУБД. Считается, что результат большинства выражений допускает значение NULL, даже если используются только столбцы, для которых значение NULL запрещено, так как при возможном переполнении или потере точности может получаться значение NULL. Для выяснения допустимости значения NULL в вычисляемом столбце таблицы используйте функцию COLUMNPROPERTY со свойством AllowsNull. Добиться того, чтобы выражение не допускало значения NULL, можно, указав ISNULL с константой check_expression, где константа представляет собой ненулевое значение, заменяющее любое значение 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 из определения таблицы либо наоборот, принимается во внимание только определение ограничения, а все остальное не учитывается.
В этом контексте default не является ключевым словом. Это идентификатор файловой группы по умолчанию, который должен иметь разделители, как в выражении ON «default» или ON [default] . Если «default» задано, QUOTED_IDENTIFIER параметр должен быть ВКЛЮЧЕН для текущего сеанса. Этот параметр принимается по умолчанию. Дополнительные сведения см. в описании SET QUOTED_IDENTIFIER.
После создания секционированной таблицы рекомендуется присвоить параметру LOCK_ESCALATION для таблицы значения AUTO . При этом можно усовершенствовать параллелизм, разрешив укрупнение блокировок до уровня секции (HoBT) вместо таблицы. Дополнительные сведения см. в разделе ALTER TABLE.
TEXTIMAGE_ON < filegroup | «default» >
Указывает, что столбцы типов text, ntext, image, xml, varchar(max), nvarchar(max), varbinary(max), а также определяемых пользователем типов данных CLR (включая geometry и geography) хранятся в указанной файловой группе.
Параметр TEXTIMAGE_ON недопустим, если в таблице нет столбцов с большими значениями. Нельзя указывать параметр TEXTIMAGE_ON одновременно с параметром partition_scheme. Если указано значение «default» или параметр TEXTIMAGE_ON не определен вообще, столбцы с большими значениями сохраняются в файловой группе по умолчанию. Способ хранения любых данных столбцов с большими значениями, определенный инструкцией CREATE TABLE , изменить в дальнейшем невозможно.
varchar(max), nvarchar(max), varbinary(max), xml и большие значения UDT хранятся прямо в строке данных до предельного размера в 8000 байт и пока значение умещается в записи. Если значение не умещается в записи, то указатель хранится в строке, а все остальное хранится вне строки в области хранения объектов LOB. 0 — это значение по умолчанию, указывающее, что все значения сохраняются прямо в строке данных.
Параметр TEXTIMAGE_ON изменяет только расположение «пространства хранения объектов LOB», но не влияет на данные, хранящиеся в строке. Используйте большие типы значений из параметра строки sp_tableoption для хранения всего бизнес-значения вне строки.
В этом контексте default не является ключевым словом. Это идентификатор файловой группы по умолчанию, который должен иметь разделители, как в выражении TEXTIMAGE_ON «default» или TEXTIMAGE_ON [default] . Если «default» задано, QUOTED_IDENTIFIER параметр должен быть ВКЛЮЧЕН для текущего сеанса. Этот параметр принимается по умолчанию. Дополнительные сведения см. в описании SET QUOTED_IDENTIFIER.
FILESTREAM_ON < partition_scheme_name | filegroup | «default» >
Область применения: SQL Server 2008 R2 (10.50.x) и более поздних версий. База данных SQL Azure и Управляемый экземпляр SQL Azure не поддерживают FILESTREAM .
Задает файловую группу для данных FILESTREAM.
Если таблица содержит данные FILESTREAM и является секционированной, необходимо включить предложение FILESTREAM_ON и указать схему секционирования файловых групп файлового потока. В этой схеме секционирования должны использоваться те же функции и столбцы секционирования, что и в схеме секционирования для таблицы; в противном случае возникает ошибка.
Если таблица не секционирована, столбец FILESTREAM не может быть секционирован. Данные FILESTREAM для таблицы должны храниться в отдельной файловой группе. Эта файловая группа указывается в предложении FILESTREAM_ON.
Если таблица не является секционированной и предложение FILESTREAM_ON не указано, используется файловая группа FILESTREAM, для которой задано свойство DEFAULT . При отсутствии файловой группы FILESTREAM возникает ошибка.
Как и в случае с предложениями ON и TEXTIMAGE_ON , значение, указанное с помощью инструкции CREATE TABLE для предложения FILESTREAM_ON , не может быть изменено, за исключением описанных ниже ситуаций.
- Инструкция CREATE INDEX преобразует кучу в кластеризованный индекс. В этом случае можно указать другую файловую группу FILESTREAM, схему секционирования или значение NULL.
- Инструкция DROP INDEX преобразует кластеризованный индекс в кучу. В этом случае можно указать другую файловую группу FILESTREAM, схему секционирования. «default»
Для файловой группы в предложении FILESTREAM_ON либо для каждой файловой группы FILESTREAM, упомянутой в схеме секционирования, должен быть определен файл. Этот файл должен быть определен с помощью инструкцииCREATE DATABASE или ALTER DATABASE, иначе возникает ошибка.
[ type_schema_name. ] type_name
Указывает тип данных столбца и схему, к которой он принадлежит. Для дисковых таблиц используйте один из следующих типов данных:
- Системный тип данных.
- Псевдоним, основанный на системном типе данных SQL Server. Прежде чем псевдонимы типов данных можно будет использовать в определении таблицы, их нужно создать с помощью инструкции CREATE TYPE . Состояние признака NULL или NOT NULL для псевдонима типа данных можно переопределить с помощью инструкции CREATE TABLE . Однако его длину изменить нельзя; длина типа данных-псевдонима не определяется инструкцией CREATE TABLE .
- Определяемый пользователем тип данных CLR. Прежде чем определяемые пользователем типы данных CLR можно будет использовать в определении таблицы, их нужно создать с помощью инструкции CREATE TYPE . Для создания столбца с определяемым пользователем типом данных CLR требуется разрешение REFERENCES на этот тип.
Если аргумент type_schema_name не указан, компонент SQL Server Database Engine ссылается на аргумент type_name в следующем порядке:
- Системный тип данных SQL Server.
- в установленной по умолчанию для текущего пользователя схеме в текущей базе данных;
- Схема dbo в текущей базе данных.
Список системных типов данных, поддерживаемых оптимизированными для памяти таблицами, см. в разделе Поддерживаемые типы данных для выполняющейся в памяти OLTP.
- precision Точность указанного типа данных. Дополнительные сведения о допустимых значениях точности см. в разделе Точность, масштаб и длина.
- scale Масштаб указанного типа данных. Дополнительные сведения о допустимых значениях масштаба см. в разделе Точность, масштаб и длина.
- max Применяется только к типам данных varchar, nvarchar и varbinary для хранения 2^31 байт символьных и двоичных данных или 2^30 байт данных в Юникоде.
CONTENT
Определяет, что каждый экземпляр типа данных xml в column_name может включать в себя несколько элементов верхнего уровня. Аргумент CONTENT применим только к данным типа xml и может быть указан только в том случае, если одновременно указан аргумент xml_schema_collection. Если этот параметр не указан, CONTENT принимается в качестве поведения по умолчанию.
DOCUMENT
Определяет, что каждый экземпляр типа данных xml в column_name может включать в себя только один элемент верхнего уровня. Аргумент DOCUMENT применим только к данным типа xml и может быть указан только в том случае, если одновременно указан аргумент xml_schema_collection.
xml_schema_collection
Применим только к типу данных xml для коллекции схем XML, связанной с этим типом. Перед помещением столбца xml в схему она должна быть создана в базе данных при помощи инструкции CREATE XML SCHEMA COLLECTION.
ПО УМОЛЧАНИЮ
Указывает значение, присваиваемое столбцу в случае отсутствия явно заданного значения при вставке. Определения DEFAULT могут применяться к любым столбцам, кроме имеющих тип timestamp или обладающих свойством IDENTITY . Если значение по умолчанию указывается для столбца определяемого пользователем типа, этот тип должен поддерживать неявное преобразование выражения constant_expression в определяемый пользователем тип. Определения DEFAULT удаляются, когда таблица удаляется из памяти. В качестве значения по умолчанию могут использоваться только константы (например, символьные строки), скалярные функции (системные, определяемые пользователем или функции CLR) или значение NULL. Для обеспечения совместимости с более ранними версиями SQL Server можно назначить имя ограничения default.
- constant_expression Константа, значение NULL или системная функция, используемая в качестве значения столбца по умолчанию.
- memory_optimized_constant_expression Константа, значение NULL или системная функция, используемая в качестве значения столбца по умолчанию. Должно поддерживаться для хранимых процедур, скомпилированных в собственном коде. Дополнительные сведения о встроенных функциях в хранимых процедурах, компилируемых в собственном коде, см. в разделе Поддерживаемые функции для модулей, скомпилированных в собственном коде T-SQL.
IDENTITY
Указывает, что новый столбец является столбцом идентификаторов. При добавлении новой строки в таблицу ядро СУБД предоставляет уникальное добавочное значение для столбца. Столбцы идентификаторов обычно используются с ограничением PRIMARY KEY для поддержания уникальности идентификаторов строк в таблице. Свойство IDENTITY может назначаться столбцам типа tinyint, smallint, int, bigint, decimal(p, 0) или numeric(p, 0). Для каждой таблицы можно создать только один столбец идентификаторов. Ограниченные значения по умолчанию и ограничения DEFAULT не могут использоваться в столбце идентификаторов. Необходимо указать как начальное значение, так и приращение, или же не указывать ничего. Если ничего не указано, применяется значение по умолчанию (1,1).
- seed Значение, используемое для первой строки, загружаемой в таблицу.
- increment Значение приращения, добавляемое к значению идентификатора предыдущей загруженной строки.
NOT FOR REPLICATION
В инструкции CREATE TABLE предложение NOT FOR REPLICATION может указываться для свойства IDENTITY, а также ограничений FOREIGN KEY и CHECK. Если это предложение указано для свойства IDENTITY , значения в столбцах идентификаторов не приращиваются, если вставку выполняют агенты репликации. Если ограничение сопровождается этим предложением, оно не выполняется, когда агенты репликации выполняют операции вставки, обновления или удаления.
GENERATED ALWAYS AS < ROW | TRANSACTION_ID | SEQUENCE_NUMBER > < START | END >[ HIDDEN ] [ NOT NULL ]
Область применения: SQL Server 2016 (13.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Определяет столбец, используемый системой для автоматического сбора сведений о версиях строк в таблице и связанной таблице журнала (если для таблицы используется системное управление версиями и таблица журнала). Используйте этот аргумент с параметром WITH SYSTEM_VERSIONING = ON для создания таблиц с системным управлением версиями: темпоральных таблиц или таблиц реестра. Дополнительные сведения см. в разделах об обновляемых таблицах реестра и темпоральных таблицах.
При попытке указать столбец, который не соответствует приведенному выше типу данных или требованиям к допустимости значений NULL, система выдаст ошибку. Если допустимость значений NULL не указана явным образом, система самостоятельно определит для столбца модификатор NULL или NOT NULL в соответствии с приведенными выше требованиями.
INDEX index_name [ CLUSTERED | NONCLUSTERED ] ( column_name [ ASC | DESC ] [ . n ] )
Область применения: SQL Server 2014 (12.x) и более поздние версии, а также База данных SQL Azure.
Задает создание индекса для таблицы. Это может быть кластеризованный или некластеризованный индекс. Индекс будет содержать указанные столбцы и сортировать данные по возрастанию или убыванию.
INDEX index_name CLUSTERED COLUMNSTORE
Область применения: SQL Server 2014 (12.x) и более поздние версии, а также База данных SQL Azure.
Задает сохранение всей таблицы в виде столбцов с кластеризованным индексом columnstore. Сюда всегда входят все столбцы в таблице. Данные не сортируются в алфавитном или числовом порядке, поскольку организация строк позволяет использовать преимущества сжатия columnstore.
INDEX index_name [ NONCLUSTERED ] COLUMNSTORE ( column_name [ . n ] )
Область применения: SQL Server 2014 (12.x) и более поздние версии, а также База данных SQL Azure.
Задает создание некластеризованного индекса columnstore в таблице. Базовая таблица может быть кучей rowstore или кластеризованным индексом или кластеризованным индексом columnstore. В любом случае при создании некластеризованного индекса columnstore в таблице сохраняется вторая копия данных для столбцов в индексе.
Некластеризованный индекс columnstore хранится и управляется как кластеризованный индекс columnstore. Он называется некластеризованным индексом columnstore, потому что столбцы могут быть ограничены и он существует как дополнительный индекс в таблице.
ON partition_scheme_name ( column_name )
Задает схему секционирования, которая определяет файловые группы, соответствующие секциям секционированного индекса. Схема секционирования должна быть создана в базе данных путем выполнения инструкции CREATE PARTITION SCHEME или ALTER PARTITION SCHEME. column_name указывает столбец, по которому будет секционирован индекс. Столбец должен соответствовать по типу данных, длине и точности аргументу функции секционирования, используемой аргументом partition_scheme_name. column_name необязательно должен соответствовать столбцам из определения индекса. Можно указать любой столбец базовой таблицы, за исключением случая секционирования индекса UNIQUE, когда аргумент column_name должен быть выбран из используемых в качестве уникального ключа. Это ограничение позволяет ядро СУБД проверять уникальность значений ключей только в одной секции.
При секционировании не уникального кластеризованного индекса ядро СУБД по умолчанию добавляет столбец секционирования в список кластеризованных ключей индекса, если он еще не указан. При секционировании неукластеризованного индекса ядро СУБД добавляет столбец секционирования в виде неключевых (включенных) столбцов индекса, если он еще не указан.
Если partition_scheme_name или filegroup не задан, а таблица секционирована, индекс помещается в ту же схему секционирования и с тем же столбцом секционирования, что и для базовой таблицы.
Для XML-индекса задать схему секционирования невозможно. Если базовая таблица секционирована, XML-индекс использует ту же схему секционирования, что и таблица.
Дополнительные сведения об индексах секционирования см. в разделе Секционированные таблицы и индексы.
ON filegroup_name
Создает заданный индекс в указанной файловой группе. Если местоположение не указано и таблица или представление не секционированы, индекс использует ту же файловую группу, что и базовая таблица или базовое представление. Файловая группа должна существовать.
ON «default»
Создает заданный индекс в файловой группе, используемой по умолчанию.
В этом контексте default не является ключевым словом. Это идентификатор файловой группы по умолчанию, который должен иметь разделители, как в выражении ON «default» или ON [default] . Если «default» задано, QUOTED_IDENTIFIER параметр должен быть ВКЛЮЧЕН для текущего сеанса. Этот параметр принимается по умолчанию. Дополнительные сведения см. в описании SET QUOTED_IDENTIFIER.
[ FILESTREAM_ON < filestream_filegroup_name | partition_scheme_name | «NULL» > ]
Область применения: SQL Server 2008 R2 (10.50.x) и более поздних версий.
Указывает размещение данных FILESTREAM для таблицы при создании кластеризованного индекса. Предложение FILESTREAM_ON позволяет перемещать данные FILESTREAM в другую файловую группу FILESTREAM или схему секционирования.
Аргумент filestream_filegroup_name указывает имя файловой группы FILESTREAM. В файловой группе должен быть определен один файл для файловой группы с помощью инструкции CREATE DATABASE или ALTER DATABASE, иначе возникает ошибка.
Если таблица секционирована, должно быть включено предложение FILESTREAM_ON и указана схема секционирования файловых групп FILESTREAM, использующая ту же функцию и те же столбцы секционирования, что и схема секционирования для таблицы. В противном случае произойдет ошибка.
Если таблица не секционирована, столбец FILESTREAM не может быть секционирован. Данные FILESTREAM для этой таблицы необходимо хранить в отдельной файловой группе, указанной в предложении FILESTREAM_ON .
FILESTREAM_ON NULL можно указать в инструкции CREATE INDEX , если создается кластеризованный индекс и таблица не содержит столбец FILESTREAM.
Дополнительные сведения см. в статье FILESTREAM (SQL Server).
ROWGUIDCOL
Указывает, что новый столбец является столбцом идентификаторов GUID строки. Только один столбец типа uniqueidentifier в таблице может быть назначен в качестве столбца ROWGUIDCOL. Применение свойства ROWGUIDCOL позволяет ссылаться на столбец с помощью ключевого слова $ROWGUID . Свойство ROWGUIDCOL может быть присвоено только столбцу типа uniqueidentifier. Ключевым словом ROWGUIDCOL нельзя обозначать столбцы определяемых пользователем типов данных.
Свойство ROWGUIDCOL не обеспечивает уникальности значений, хранимых в столбце. Кроме того, при указании данного свойства автоматического формирования значений для новых строк, вставляемых в таблицу, не выполняется. Для создания уникальных значений в каждом столбце следует использовать функцию NEWID или NEWSEQUENTIALID в инструкциях INSERT либо использовать эти функции по умолчанию для столбца.
ENCRYPTED WITH
Указывает столбцы шифрования с помощью функции Always Encrypted.
- COLUMN_ENCRYPTION_KEY = key_name Указывает пустой ключ шифрования столбца. Дополнительные сведения см. в этой статье.
- ENCRYPTION_TYPE = < DETERMINISTIC | RANDOMIZED >Детерминированное шифрование использует метод, который всегда создает одно и то же зашифрованное значение для любого текстового значения. Это позволяет выполнять поиск с помощью сравнения на равенство, группирование и объединение таблиц по зашифрованным значениям. При этом несанкционированные пользователи могут определять некоторую информацию о зашифрованных значениях путем анализа повторов в зашифрованном столбце. Соединить две таблицы по столбцам с детерминированным шифрованием можно только в том случае, если оба столбца шифруются с помощью одного ключа шифрования столбца. При использовании детерминированного шифрования необходимо указать порядок сортировки binary2 в параметрах сортировки для символьных столбцов. Случайное шифрование использует метод, который шифрует данные менее предсказуемым образом. Случайное шифрование более безопасное, но не предусматривает вычисления и индексацию в зашифрованных столбцах, если экземпляр SQL Server не поддерживает функцию Always Encrypted с безопасными анклавами. Дополнительные сведения см. в статье Always Encrypted с безопасными анклавами. Если вы используете функцию Always Encrypted (без безопасных анклавов), к столбцам, поиск которых осуществляется на основе параметров или параметров группирования, например номер внутреннего паспорта, следует применять детерминированное шифрование. Используйте случайное шифрование для таких данных, как номер кредитной карты, которые не группируются с другими записями, не используются для соединения таблиц и не могут быть параметром поиска, так как для поиска нужной строки с зашифрованным столбцом используются другие столбцы (например, номер транзакции). При использовании функции Always Encrypted с безопасными анклавами советуем использовать случайное шифрование. Столбцы должны иметь подходящий тип данных.
- ALGORITHM Область применения: SQL Server 2016 (13.x) и более поздних версий. Этот параметр должен содержать значение ‘AEAD_AES_256_CBC_HMAC_SHA_256’ . Дополнительные сведения о функции Always Encrypted, в том числе об ограничениях, см. в этой статье.
SPARSE
Указывает, что столбец является разреженным столбцом. Хранилище разреженных столбцов оптимизируется для значений NULL. Для разреженных столбцов нельзя указать параметр NOT NULL. Дополнительные ограничения и сведения о разреженных столбцах см. в разделе Разреженные столбцы.
MASKED WITH ( FUNCTION = ‘mask_function‘ )
Область применения: SQL Server 2016 (13.x) и более поздних версий.
Указывает маску для динамического маскирования данных. mask_function — это имя функции маскирования с соответствующими параметрами. Доступны четыре функции:
- default()
- email()
- partial()
- random()
Требуется разрешение ALTER ANY MASK .
FILESTREAM
Область применения: SQL Server 2008 R2 (10.50.x) и более поздних версий.
Допустимо только для столбцов типа varbinary(max). Указывает хранилище FILESTREAM для данных больших двоичных объектов типа varbinary(max).
Таблица также должна содержать столбец данных типа uniqueidentifier с атрибутом ROWGUIDCOL. Этот столбец не должен допускать значений NULL и должен иметь относящееся к одному столбцу ограничение UNIQUE или PRIMARY KEY. Значение идентификатора GUID для столбца должно быть предоставлено приложением во время вставки данных или ограничением DEFAULT, в котором используется функция NEWID ().
Столбец ROWGUIDCOL нельзя удалить, а связанные ограничения нельзя изменить, если в таблице определен столбец FILESTREAM. Столбец ROWGUIDCOL можно удалить только после удаления последнего столбца FILESTREAM.
Если для столбца задан атрибут хранилища FILESTREAM, то все значения для этого столбца хранятся в контейнере данных FILESTREAM в файловой системе.
COLLATE collation_name
Задает параметры сортировки для столбца. Могут использоваться параметры сортировки Windows или параметры сортировки SQL. Аргумент collation_name применим только к столбцам типа char, varchar, text, nchar, nvarchar и ntext. Если этот аргумент не указан, столбцу назначаются либо параметры сортировки определяемого пользователем типа, если столбец принадлежит к определяемому пользователем типу данных, либо установленные по умолчанию параметры сортировки для базы данных.
Дополнительные сведения об именах параметров сортировки Windows и SQL см. в разделах Имя параметров сортировки Windows и Имя параметров сортировки SQL.
Дополнительные сведения см. в описании COLLATE.
ОГРАНИЧЕНИЯ
Необязательное ключевое слово, указывающее на начало определения ограничения PRIMARY KEY, NOT NULL, UNIQUE, FOREIGN KEY или CHECK.
- constraint_name Имя ограничения. Имена ограничений должны быть уникальными в пределах схемы, к которой принадлежит таблица.
- NULL | NOT NULL Определяет, допустимы ли для столбца значения NULL. Параметр NULL не является ограничением в строгом смысле слова, но может быть указан так же, как и NOT NULL. Ограничение NOT NULL может быть указано для вычисляемых столбцов только в случае, если одновременно указан параметр PERSISTED.
- ПЕРВИЧНЫЙ КЛЮЧ Ограничение, которое обеспечивает целостность сущностей для указанного столбца или столбцов с помощью уникального индекса. Можно создать только одно ограничение 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. Для выполнения этого ограничения внешние ключевые столбцы должны допускать значения NULL.
- SET DEFAULT Все значения, составляющие внешний ключ, задаются по умолчанию при удалении соответствующей строки в родительской таблице. Для выполнения этого ограничения все внешние ключевые столбцы должны иметь определения по умолчанию. Если столбец допускает значения NULL и значение по умолчанию явно не определено, значением столбца по умолчанию становится NULL. Не указывайте параметр CASCADE , если таблица будет включена в публикацию слиянием, в которой используются логические записи. Дополнительные сведения о логических записях см. в статье Группирование изменений в связанных строках с помощью логических записей. Параметр ON DELETE CASCADE нельзя указывать, если в таблице уже существует триггер INSTEAD OF для условия ON DELETE . Например, в базе данных AdventureWorks2022 таблица ProductVendor имеет ссылочную связь с таблицей Vendor . Внешний ключ ProductVendor.BusinessEntityID ссылается на первичный ключ Vendor.BusinessEntityID . DELETE Если инструкция выполняется в строке таблицы Vendor , а ON DELETE CASCADE действие указано для ProductVendor.BusinessEntityID , ядро СУБД проверка для одной или нескольких зависимых строк в ProductVendor таблице. При наличии зависимые строки в ProductVendor таблице удаляются, а также строка, указанная в Vendor таблице. В противном случае, если задан параметр NO ACTION , ядро СУБД выдает ошибку и производит откат операции по удалению строки из таблицы Vendor , если в таблице ProductVendor существует хотя бы одна строка, ссылающаяся на нее.
- ON UPDATE < NO ACTION | CASCADE | SET NULL | SET DEFAULT >Указывает, какое действие совершается над строками в изменяемой таблице, когда эти строки имеют ссылочную связь и строка родительской таблицы, на которую указывает ссылка, обновляется. Параметр по умолчанию — NO ACTION.
- NO ACTION Ядро СУБД вызывает ошибку, а действие обновления строки в родительской таблице откатится.
- CASCADE Соответствующие строки обновляются в ссылающейся таблице, если эта строка обновляется в родительской таблице.
- SET NULL Всем значениям, составляющим внешний ключ, присваивается значение NULL, когда обновляется соответствующая строка в родительской таблице. Для выполнения этого ограничения внешние ключевые столбцы должны допускать значения NULL.
- SET DEFAULT Всем значениям, составляющим внешний ключ, присваивается их значение по умолчанию, когда обновляется соответствующая строка в родительской таблице. Для выполнения этого ограничения все внешние ключевые столбцы должны иметь определения по умолчанию. Если столбец допускает значения NULL и значение по умолчанию явно не определено, значением столбца по умолчанию становится NULL. Не указывайте параметр CASCADE , если таблица будет включена в публикацию слиянием, в которой используются логические записи. Дополнительные сведения о логических записях см. в статье Группирование изменений в связанных строках с помощью логических записей. Действия ON UPDATE CASCADE , SET NULL и SET DEFAULT нельзя определить, если в изменяемой таблице уже существует триггер INSTEAD OF для условия ON UPDATE . Например, в AdventureWorks2022 базе данных ProductVendor таблица имеет ссылку на Vendor таблицу: ProductVendor.BusinessEntity внешний ключ ссылается на первичный Vendor.BusinessEntityID ключ. Если инструкция UPDATE выполняется в строке таблицы Vendor , а для действия ON UPDATE CASCADE указано ProductVendor.BusinessEntityID ядро СУБД проверка для одной или нескольких зависимых строк в ProductVendor таблице. При наличии зависимые строки в ProductVendor таблице обновляются, а также строка, указанная в Vendor таблице. В противном случае, если задан параметр NO ACTION, ядро СУБД выдает ошибку и производит откат операции по обновлению строки в таблице Vendor , если в таблице ProductVendor существует хотя бы одна строка, ссылающаяся на нее.
- ПРОВЕРКА Ограничение, обеспечивающее целостность домена путем ограничения возможных значений, которые могут быть введены в столбец или столбцы. Ограничения CHECK в вычисляемых столбцах должны быть также помечены как PERSISTED.
- logical_expression Логическое выражение, возвращающее значения TRUE или FALSE. Псевдонимы типа данных частью выражения быть не могут.
- column_name Столбец или список столбцов (в скобках), используемый в ограничениях таблицы для указания столбцов, используемых в определении ограничения.
- [ ASC | DESC ] Указывает порядок сортировки столбца или столбцов, участвующих в ограничениях таблицы. Значение по умолчанию — ASC.
- partition_scheme_name Имя схемы секционирования, определяющей файловые группы, которым сопоставляются секции секционированной таблицы. Эта схема секционирования должна существовать в базе данных.
- [ partition_column_name. ] Указывает столбец, по которому будет секционирована таблица. Столбец должен совпадать с указанным в функции секционирования, которая используется аргументом partition_scheme_name, по типу данных, длине и точности. Вычисляемый столбец, участвующий в функции секционирования, должен быть явно обозначен ключевым словом PERSISTED.
Важно! Рекомендуется указывать параметр NOT NULL для столбца секционирования секционированных таблиц, а также для несекционированных таблиц, являющихся источниками или целями для операций ALTER TABLE. SWITCH. В результате любые ограничения CHECK, заданные для столбцов секционирования, не будут проверять значения NULL.
Важно! Описание выражения WITH FILLFACTOR = fillfactor как единственного параметра индекса, применимого к ограничениям PRIMARY KEY или UNIQUE, сохранено для обеспечения обратной совместимости, но в будущих выпусках это выражение документировано не будет.
column_set_name XML COLUMN_SET FOR ALL_SPARSE_COLUMNS
Имя набора столбцов. Набор столбцов представляет собой нетипизированное XML-представление, в котором все разреженные столбцы таблицы объединены в структурированные выходные данные. Дополнительные сведения о наборах столбцов см. в разделе Использование наборов столбцов.
PERIOD FOR SYSTEM_TIME ( system_start_time_column_name , system_end_time_column_name )
Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure.
Указывает имена столбцов, которые система будет использовать для обозначения периода действия записи. Используйте этот аргумент с аргументами GENERATED ALWAYS AS ROW < START | END >и WITH SYSTEM_VERSIONING = ON , чтобы создать темпоральную таблицу. Дополнительные сведения см. в разделе Temporal Tables.
COMPRESSION_DELAY
Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure.
Если используется оптимизация для памяти, указывается минимальное количество минут задержки, в течение которых строка должна оставаться в таблице без изменений до сжатия в индекс columnstore. SQL Server выбирает определенные строки для сжатия в зависимости от времени их последнего обновления. Например, если строки часто меняются в течение двухчасового периода, установите COMPRESSION_DELAY = 120 Minutes , чтобы обновления были завершены до того, как SQL Server сожмет строку.
Для таблицы на основе диска значение delay указывает минимальное количество минут, в течение которых разностная группа строк в состоянии CLOSED должна оставаться в разностной группе строк до того, как SQL Server сожмет ее в сжатую группу строк. Поскольку таблицы на основе диска не отслеживают время вставки и обновления отдельных строк, SQL Server применяет задержку к разностным группам строк в состоянии CLOSED.
Значение по умолчанию — 0 минут.
Указывает один или более параметров таблицы.
DATA_COMPRESSION
Задает режим сжатия данных для указанной таблицы, номера секции или диапазона секций. Существуют следующие варианты выбора.
- NONE Таблица или указанные секции не сжимаются.
- ROW Таблицы или указанные секции сжимаются, используя сжатие строк.
- СТРАНИЦА Таблицы или указанные секции сжимаются, используя сжатие страниц.
- COLUMNSTORE Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure. Применяется только к индексам columnstore, включая некластеризованные и кластеризованные индексы columnstore. COLUMNSTORE задает сжатие с использованием самого эффективного сжатия columnstore. Это обычный вариант.
- COLUMNSTORE_ARCHIVE Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure. Применяется только к индексам columnstore, включая некластеризованные и кластеризованные индексы columnstore. Параметр COLUMNSTORE_ARCHIVE обеспечивает дальнейшее сжатие таблицы или секции до еще меньшего размера. Это может использоваться для архивации или в других ситуациях, где требуется уменьшение объема пространства и допускается увеличение затрат времени на сохранение и выборку
Дополнительные сведения см. в разделе Data Compression.
XML_COMPRESSION
Область применения: SQL Server 2022 (16.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Задает параметр сжатия XML для всех столбцов с типом данных xml в таблице. Существуют следующие варианты выбора.
- DNS Столбцы, использующие тип данных xml, сжимаются.
- ВЫКЛ. Столбцы, использующие тип данных xml, не сжимаются.
ON PARTITIONS ( < | [ . n ] )
Указывает разделы, к которым применяется параметр DATA_COMPRESSION или XML_COMPRESSION . Если таблица не секционирована, аргумент ON PARTITIONS приведет к возникновению ошибки. Если не указано предложение ON PARTITIONS , параметр DATA_COMPRESSION применяется ко всем секциям секционированной таблицы.
partition_number_expression можно указать одним из следующих способов:
- Указав номер секции, например: ON PARTITIONS (2)
- Указав номера нескольких секций, разделив их запятыми, например ON PARTITIONS (1, 5)
- Указав диапазоны секций и отдельные секции, например ON PARTITIONS (2, 4, 6 TO 8)
можно указать в виде номеров секций, разделенных ключевым словом TO, например: ON PARTITIONS (6 TO 8) .
Чтобы для разных секций задать разные типы сжатия данных, укажите параметр DATA_COMPRESSION несколько раз, например следующим образом:
WITH ( DATA_COMPRESSION = NONE ON PARTITIONS (1), DATA_COMPRESSION = ROW ON PARTITIONS (2, 4, 6 TO 8), DATA_COMPRESSION = PAGE ON PARTITIONS (3, 5) )Параметр XML_COMPRESSION можно указывать несколько раз, например:
WITH ( XML_COMPRESSION = OFF ON PARTITIONS (1), XML_COMPRESSION = ON ON PARTITIONS (2, 4, 6 TO 8), XML_COMPRESSION = OFF ON PARTITIONS (3, 5) );Указывает один или более параметров индекса. Полное описание этих параметров см. в этой статье.
PAD_INDEX =
Если указано значение ON, процент свободного места, определяемый параметром FILLFACTOR, применяется к страницам индекса промежуточного уровня. Если указано значение OFF или значение FILLFACTOR не указано, страницы промежуточного уровня заполняются до приблизительного объема, оставляющего достаточно места для, как минимум, одной строки максимального размера, которого может достигать индекс, при этом учитывается набор ключей на промежуточных страницах. Значение по умолчанию — OFF.
FILLFACTOR = fillfactor
Указывает процент, указывающий, насколько полный ядро СУБД должен сделать конечный уровень каждой страницы индекса во время создания или изменения индекса. Значение fillfactor должно быть целым числом от 1 до 100. По умолчанию установлено значение 0. Значения коэффициентов заполнения 0 и 100 идентичны.
IGNORE_DUP_KEY =
Определяет ответ на ошибку, случающуюся, когда операция вставки пытается вставить в уникальный индекс повторяющиеся значения ключа. Параметр IGNORE_DUP_KEY применяется только к операциям вставки, производимым после создания или перестроения индекса. Параметр не работает во время выполнения инструкции CREATE INDEX, ALTER INDEX или UPDATE. Значение по умолчанию — OFF.
- DNS Если в уникальный индекс вставляются повторяющиеся значения ключа, выводится предупреждающее сообщение. С ошибкой завершаются только строки, нарушающие ограничение уникальности.
- ВЫКЛ. Если в уникальный индекс вставляются повторяющиеся значения ключа, выводится сообщение об ошибке. Будет выполнен откат всей операции INSERT.
Для IGNORE_DUP_KEY нельзя установить значение ON для индексов, создаваемых для представлений, неуникальных индексов, XML-индексов, пространственных индексов и фильтруемых индексов.
Для просмотра значения IGNORE_DUP_KEY используйте sys.indexes.
Для обратной совместимости синтаксиса аргумент WITH IGNORE_DUP_KEY эквивалентен WITH IGNORE_DUP_KEY = ON .
STATISTICS_NORECOMPUTE =
Если указано значение ON, автоматический пересчет устаревших статистик индекса не производится. Если указано значение OFF, включается автоматическое обновление статистик. Значение по умолчанию — OFF.
ALLOW_ROW_LOCKS =
Если указано значение ON, при доступе к индексу допустимы блокировки строк. Ядро СУБД определяет, когда используются блокировки строк. При значении OFF блокировки строк не используются. Значение по умолчанию — ON.
ALLOW_PAGE_LOCKS =
Если указано значение ON, при доступе к индексу допустимы блокировки страниц. Ядро СУБД определяет, когда используются блокировки страниц. При значении OFF блокировки страниц не используются. Значение по умолчанию — ON.
OPTIMIZE_FOR_SEQUENTIAL_KEY =
Область применения: SQL Server 2019 (15.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Определяет, следует ли выполнять оптимизацию, связанную с состязанием при операциях вставки на последнюю страницу. Значение по умолчанию — OFF. См. подробнее раздел о последовательных ключах в документации по CREATE INDEX.
FILETABLE_DIRECTORY = directory_name
Область применения: SQL Server 2012 (11.x) и более поздних версий.
Указывает имя каталога таблицы FileTable, совместимое с Windows. Это имя должно быть уникальным среди всех имен каталогов FileTable в базе данных. Проверка уникальности выполняется без учета регистра, независимо от параметров сортировки. Если это значение не задано, то используется имя таблицы FileTable.
FILETABLE_COLLATE_FILENAME = < collation_name | database_default >
Область применения: SQL Server 2012 (11.x) и более поздних версий. База данных SQL Azure и Управляемый экземпляр SQL Azure не поддерживают FILETABLE .
Указывает имя параметров сортировки, применяемых к Name столбцу в FileTable. Для соответствия семантике именования файлов в операционной системе Windows параметры сортировки не должны учитывать регистр. Если это значение не задано, то используются параметры сортировки по умолчанию базы данных. Если в параметрах сортировки по умолчанию базы данных учитывается регистр, то выдается ошибка и операция CREATE TABLE оканчивается неуспешно.
- collation_name Имя параметров сортировки, не учитывающих регистр.
- database_default Указывает, что для базы данных следует использовать параметры сортировки по умолчанию. Эти параметры сортировки не должны учитывать регистр символов.
FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME = constraint_name
Область применения: SQL Server 2012 (11.x) и более поздних версий. База данных SQL Azure и Управляемый экземпляр SQL Azure не поддерживают FILETABLE .
Указывает имя, которое должно использоваться для ограничения первичного ключа, автоматически создаваемого в FileTable. Если это значение не задано, то имя для ограничения формируется системой.
FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME = constraint_name
Область применения: SQL Server 2012 (11.x) и более поздних версий. База данных SQL Azure и Управляемый экземпляр SQL Azure не поддерживают FILETABLE .
Указывает имя, которое должно использоваться для ограничения уникальности, автоматически создаваемого в столбце stream_id в FileTable. Если это значение не задано, то имя для ограничения формируется системой.
FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME = constraint_name
Область применения: SQL Server 2012 (11.x) и более поздних версий. База данных SQL Azure и Управляемый экземпляр SQL Azure не поддерживают FILETABLE .
Указывает имя, которое должно использоваться для ограничения уникальности, автоматически создаваемого в столбцах parent_path_locator и name в FileTable. Если это значение не задано, то имя для ограничения формируется системой.
SYSTEM_VERSIONING = ON [ ( HISTORY_TABLE = schema_name.history_table_name [ , DATA_CONSISTENCY_CHECK = < ON | OFF >] ) ]
Область применения: SQL Server 2016 (13.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Допускает системное управление версиями таблицы, если выполнены требования по типу данных, ограничении допустимости значений NULL и ограничении первичного ключа. Эта система будет записывать журнал каждой записи из таблицы с системным управлением версиями в отдельную таблицу журнала. Если аргумент HISTORY_TABLE не используется, этой таблице журнала будет присвоено имя MSSQL_TemporalHistoryFor . Если при создании таблицы журнала указывается ее имя, следует также указать имя схемы и таблицы.
Если таблица журнала не существует, система создает новую таблицу журнала, соответствующую схеме текущей таблицы, в той же файловой группе, что и текущая таблица. При этом между двумя таблицами создается связь, и система записывает журнал каждой записи в текущей таблице в таблицу журнала. По умолчанию таблица журнала сжимается с использованием метода PAGE .
Если аргумент HISTORY_TABLE используется для создания ссылки и применения существующей таблицы журнала, ссылка создается между текущей таблицей и указанной таблицей. Если текущая таблица секционирована, таблица журнала создается в файловой группе по умолчанию, так как конфигурация секционирования не реплицируется автоматически из текущей таблицы в таблицу журнала. При создании ссылки на существующую таблицу журнала вы можете указать необходимость проверки согласованности данных. Проверка согласованности данных гарантирует, что существующие записи не перекрываются. Проверка согласованности данных является проверкой по умолчанию.
Используйте этот аргумент с аргументами PERIOD FOR SYSTEM_TIME и GENERATED ALWAYS AS ROW < START | END >, чтобы выключить системное управление версиями в таблице. Дополнительные сведения см. в разделе Temporal Tables. Используйте этот аргумент с аргументом WITH LEDGER = ON , чтобы создать обновляемую таблицу реестра. Использование существующих таблиц журнала с таблицами реестра не допускается.
REMOTE_DATA_ARCHIVE = < ON [ ( table_stretch_options [ . n ] ) ] | OFF ( MIGRATION_STATE = PAUSED ) >
Область применения: SQL Server 2016 (13.x) и более поздних версий.
Создание новой таблицы, для которой включена или отключена Stretch Database. Дополнительные сведения см. в разделе Stretch Database.
Stretch Database устарел в SQL Server 2022 (16.x) и База данных SQL Azure. Эта функция будет удалена в будущей версии ядро СУБД. Избегайте использования этого компонента в новых разработках и запланируйте изменение существующих приложений, в которых он применяется.
Включение Stretch Database для таблицы
Если вы включаете Stretch для таблицы, указывая ON , вы можете дополнительно указать MIGRATION_STATE = OUTBOUND , чтобы сразу же приступить к переносу данных, или MIGRATION_STATE = PAUSED , чтобы отложить его. Значение по умолчанию — MIGRATION_STATE = OUTBOUND . Более подробную информацию о включении Stretch для таблицы см. в разделе Включение Stretch Database для таблицы.
Предварительные требования. Прежде чем включить Stretch для таблицы, необходимо включить Stretch на сервере и в базе данных. Дополнительные сведения см. в разделе Enable Stretch Database for a database.
Разрешения. Чтобы включить Stretch для таблицы или базы данных, требуются права db_owner. Чтобы включить Stretch для таблицы, нужно иметь разрешения ALTER для таблицы.
[ FILTER_PREDICATE = < NULL | predicate > ]
Область применения: SQL Server 2016 (13.x) и более поздних версий.
Дополнительно указывает предикат фильтра для выбора строк для миграции из таблицы, которая содержит данные журнала и текущие данные. Этот предикат должен вызывать детерминированную встроенную функцию с табличным значением. Более подробную информацию см. в разделе Включение Stretch Database для таблицы и Выбор строк для миграции с помощью функции фильтра.
Если указать плохо оптимизированный предикат фильтра, перенос данных будет выполняться медленно. Stretch Database применяет предикат фильтра к таблице при помощи оператора CROSS APPLY.
Если предикат фильтра не указан, переносится вся таблица.
Если вы указываете предикат фильтра, необходимо также указать MIGRATION_STATE.
MIGRATION_STATE =
Область применения: SQL Server 2016 (13.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
- Укажите OUTBOUND для переноса данных из SQL Server в База данных SQL Azure.
- Укажите INBOUND , чтобы скопировать удаленные данные для таблицы из База данных SQL Azure обратно в SQL Server и отключить Stretch для таблицы. Дополнительные сведения см. в разделе Отключение Stretch Database и возврат удаленных данных. Эта операция предусматривает расходы на передачу данных и не может быть отменена.
- Укажите PAUSED для приостановки миграции данных. Дополнительные сведения см. в разделе Приостановка и возобновление переноса данных (Stretch Database).
[ DATA_DELETION = ON < ( FILTER_COLUMN = column_name, RETENTION_PERIOD = < INFINITE | number < DAY | DAYS | WEEK | WEEKS | MONTH | MONTHS | YEAR | YEARS >) > ]
Применяется только к: Только для пограничных вычислений SQL Azure
Включает очистку старых или устаревших данных из таблиц в базе данных на основе политики хранения. Дополнительные сведения см. в статье Включение и отключение хранения данных. Для включения хранения данных необходимо указать следующие параметры.
- FILTER_COLUMN = < column_name >Указывает столбец, который должен использоваться для определения того, являются ли строки в таблице устаревшими. Для столбца фильтра разрешены следующие типы данных.
- date
- datetime
- datetime2
- smalldatetime
- datetimeoffset
MEMORY_OPTIMIZED
Область применения: SQL Server 2014 (12.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure. Управляемый экземпляр SQL Azure не поддерживает оптимизированные для памяти таблицы на уровне общего назначения.
Значение ON указывает, что таблица оптимизирована для памяти. Таблицы, оптимизированные для памяти, входят в функцию выполняющейся в памяти OLTP, которая используется для оптимизации производительности обработки транзакций. Сведения о начале работы с OLTP в памяти см . в кратком руководстве 1. Технологии OLTP в памяти для ускорения производительности Transact-SQL. Дополнительные сведения об оптимизированных для памяти таблицах см. в статье Таблицы, оптимизированные для памяти.
Значение по умолчанию OFF указывает, что таблица основана на диске.
DURABILITY
Область применения: SQL Server 2014 (12.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Значение SCHEMA_AND_DATA указывает на устойчивость таблицы. Это означает, что изменения сохраняются на диске даже после перезагрузки или отработки отказа. SCHEMA_AND_DATA является значением по умолчанию.
Значение SCHEMA_ONLY указывает, что таблица не является устойчивой. При перезапуске или отработке отказа в базе данных схема таблицы сохраняется, а обновления данных — нет. Аргумент DURABILITY = SCHEMA_ONLY может использоваться только совместно с аргументом MEMORY_OPTIMIZED = ON .
Если таблица была создана с использованием аргумента DURABILITY = SCHEMA_ONLY , а впоследствии значение READ_COMMITTED_SNAPSHOT было изменено с помощью инструкции ALTER DATABASE , данные в таблице будут потеряны.
BUCKET_COUNT
Область применения: SQL Server 2014 (12.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Отображает число контейнеров, которые необходимо создать в хэш-индексе. Максимальное значение для параметра BUCKET_COUNT в хэш-индексах составляет 1 073 741 824. Дополнительные сведения о числах контейнеров см. в разделе Индексы для таблиц, оптимизированных для памяти.
Bucket_count — это обязательный аргумент.
ИНДЕКС
Область применения: SQL Server 2014 (12.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
Индексы столбцов и таблиц необходимо указывать в составе инструкции CREATE TABLE. Дополнительные сведения о добавлении и удалении индексов в таблицах, оптимизированных для памяти, см. в разделе: Изменение таблиц, оптимизированных для памяти
- ХЭШ Область применения: SQL Server 2014 (12.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure. Указывает, что был создан индекс HASH. Хэш-индексы поддерживаются только в таблицах, оптимизированных для памяти.
LEDGER = ON ( [ . n ] ) | OFF
Область применения: SQL Server 2022 (16.x), База данных SQL Azure и Управляемый экземпляр SQL Azure.
Если инструкция создает таблицу реестра, требуется разрешение ENABLE LEDGER .
Указывает, является ли создаваемая таблица таблицей реестра (ON) или нет (OFF). Значение по умолчанию — OFF. Если указан параметр APPEND_ONLY = ON , система создает таблицу реестра только для добавления, в которую можно только вставлять новые строки. В противном случае система создает обновляемую таблицу реестра. Для обновляемой таблицы реестра также требуется аргумент SYSTEM_VERSIONING = ON . Обновляемая таблица реестра должна также поддерживать системное управление версиями. Но обновляемая таблица реестра не обязательно должна быть темпоральной таблицей (для нее не требуется параметр PERIOD FOR SYSTEM_TIME ). Если таблица журнала указана с параметрами LEDGER = ON и SYSTEM_VERSIONING = ON , она не должна ссылаться на существующую таблицу.
База данных реестра (созданная с помощью параметра LEDGER = ON ) позволяет только создавать таблицы реестра. Попытки создать таблицу с помощью LEDGER = OFF приведут к ошибке. Каждая новая таблица по умолчанию создается как обновляемая таблица реестра, даже если не указано значение LEDGER = ON , которая будет иметь значения по умолчанию для всех остальных параметров.
Обновляемая таблица реестра должна содержать четыре GENERATED ALWAYS столбца, точно один столбец, определенный с каждым из следующих аргументов:
- GENERATED ALWAYS AS TRANSACTION_ID START
- GENERATED ALWAYS AS TRANSACTION_ID END
- GENERATED ALWAYS AS SEQUENCE_NUMBER START
- GENERATED ALWAYS AS SEQUENCE_NUMBER END
Таблица реестра только для добавления должна содержать один столбец, определенный с использованием следующих аргументов:
- GENERATED ALWAYS AS TRANSACTION_ID START
- GENERATED ALWAYS AS SEQUENCE_NUMBER START
Если какой-либо из обязательных столбцов GENERATED ALWAYS не определен в инструкции CREATE TABLE , но эта инструкция содержит LEDGER = ON , система автоматически попытается добавить столбец, используя применимое определение из приведенного ниже списка. Если существует конфликт имен с определенным ранее столбцом, система выдаст ошибку.
[ledger_start_transaction_id] BIGINT GENERATED ALWAYS AS TRANSACTION_ID START HIDDEN NOT NULL [ledger_end_transaction_id] BIGINT GENERATED ALWAYS AS TRANSACTION_ID END HIDDEN NULL [ledger_start_sequence_number] BIGINT GENERATED ALWAYS AS SEQUENCE_NUMBER START HIDDEN NOT NULL [ledger_end_sequence_number] BIGINT GENERATED ALWAYS AS SEQUENCE_NUMBER END HIDDEN NULLопределяет схему и имя для представления реестра, которое система автоматически создает и привязывает к таблице. Если этот параметр не указан, система создает имя представления реестра, добавляя _Ledger к имени создаваемой таблицы ( database_name.schema_name.table_name ). Если представление с указанным или созданным именем уже существует, система выдаст ошибку. Если таблица является обновляемой таблицей реестра, представление реестра создается путем объединения таблицы и связанной таблицы журнала.
Каждая строка в представлении реестра содержит сведения о создании или удалении версии строки в таблице реестра. Представление реестра содержит все столбцы таблицы реестра, за исключением указанных выше столбцов GENERATED ALWAYS. Представление реестра также содержит следующие дополнительные столбцы:
Имя столбца Тип данных Description Определяется с использованием параметра TRANSACTION_ID_COLUMN_NAME . ledger_transaction_id , если не определено. bigint Идентификатор транзакции, при выполнении которой была создана или удалена версия строки. Определяется с использованием параметра SEQUENCE_NUMBER_COLUMN_NAME . ledger_sequence_number , если не определено. bigint Порядковый номер операции на уровне строки в пределах транзакции в таблице. Определяется с использованием параметра OPERATION_TYPE_COLUMN_NAME . ledger_operation_type , если не определено. tinyint Содержит 1 ( INSERT ) или 2 ( DELETE ). При вставке строки в таблицу реестра создается новая строка в представлении реестра, содержащая 1 в этом столбце. При удалении строки из таблицы реестра в представлении реестра создается новая строка, содержащая 2 в этом столбце. При обновлении строки в таблице реестра в представлении реестра появляются две новые строки. Одна строка содержит 2 ( DELETE ) и другую строку 1 содержит ( INSERT ) в этом столбце. Определяется с использованием параметра OPERATION_TYPE_DESC_COLUMN_NAME . ledger_operation_type_desc , если не определено. NVARCHAR(128) Содержит INSERT или DELETE . Дополнительные сведения см. выше. Транзакции, включающие создание таблицы реестра, регистрируются в sys.database_ledger_transactions.
Задает параметр реестра.
[ LEDGER_VIEW = schema_name.ledger_view_name [ ( [ . n ] ) ]
Задает имя представления реестра и имена дополнительных столбцов, которые система добавляет в представление реестра.
[ APPEND_ONLY = ON | OFF ]
Указывает, является ли созданная таблица реестра доступной только для добавления или обновляемой. Значение по умолчанию — OFF .
Задает один или несколько параметров представления реестра. В каждом параметре представления реестра указывается имя столбца, которое система добавит к представлению в дополнение к столбцам, определенным в таблице реестра.
[ TRANSACTION_ID_COLUMN_NAME = transaction_id_column_name ]
Указывает имя столбца, в котором хранится идентификатор транзакции, которая создала или удалила версию строки. Имя столбца по умолчанию — ledger_transaction_id .
[ SEQUENCE_NUMBER_COLUMN_NAME = sequence_number_column_name ]
Указывает имя столбцов, хранящие порядковый номер операции на уровне строк в транзакции в таблице. Имя столбца по умолчанию — ledger_sequence_number .
[ OPERATION_TYPE_COLUMN_NAME = operation_type_id column_name ]
Указывает имя столбцов, хранющих идентификатор типа операции. Имя столбца по умолчанию — ledger_operation_type.
[ OPERATION_TYPE_DESC_COLUMN_NAME = operation_type_desc_column_name ]
Указывает имя столбцов, хранящие описание типа операции. Имя столбца по умолчанию — ledger_operation_type_desc .
Замечания
Сведения о допустимом количестве таблиц, столбцов, ограничений и индексов см. в разделе Спецификации максимально допустимых параметров SQL Server.
Пространство таблицам и индексам обычно выделяется по одному экстенту за раз. SET MIXED_PAGE_ALLOCATION Если параметр ALTER DATABASE имеет значение TRUE или всегда до SQL Server 2016 (13.x) при создании таблицы или индекса, он выделяет страницы из смешанных экстентов до тех пор, пока не будет достаточно страниц для заполнения единообразной экстенты. Каждый раз, когда число страниц достигает размера однородного экстента, и текущие выделенные экстенты становятся заполненными, выделяется новый экстент. Получить отчет об объеме выделенного и используемого таблицей пространства можно с помощью процедуры sp_spaceused .
Компонент Database Engine не требует указания параметров DEFAULT, IDENTITY, ROWGUIDCOL или ограничения столбцов в определенном порядке при определении столбца.
После создания таблицы параметр QUOTED IDENTIFIER всегда сохраняется в метаданных таблицы в состоянии ON, даже если он был установлен в состояние OFF при создании таблицы.
Временные таблицы
Можно создавать локальные и глобальные временные таблицы. Локальные временные таблицы видимы только во время текущего сеанса, а глобальные — во всех сеансах. Временные таблицы не подлежат секционированию.
Имени локальной временной таблицы должен предшествовать знак номера ( #table_name ), а имени глобальной временной таблицы — двойной знак номера ( ##table_name ).
Инструкции Transact-SQL обращаются к временной таблице по значению аргумента table_name, заданному в инструкции CREATE TABLE , например так:
CREATE TABLE #MyTempTable ( col1 INT PRIMARY KEY ); INSERT INTO #MyTempTable VALUES (1);Если в пределах одной хранимой процедуры или пакета создается более одной временной таблицы, им должны быть присвоены разные имена.
Параметр schema_name игнорируется при создании или временной таблице или обращении к ней. Все временные таблицы создаются в схеме dbo.
Если локальная временная таблица создается в хранимой процедуре или приложении, которые могут выполняться одновременно несколькими сеансами, ядро СУБД должны иметь возможность различать таблицы, созданные различными сеансами. Ядро СУБД делает это путем внутреннего добавления числовых суффиксов к каждому имени локальной временной таблицы. Полное имя временной таблицы, хранящейся в sys.sysobjects таблице, состоит из имени таблицы tempdb , указанной в инструкции 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 обращение к временным таблицам недопустимо.
При создании таблицы с именованным ограничением внутри области, определяемой пользователем транзакции, возможность выполнения инструкций, формирующих временные таблицы, ограничивается одним пользователем единовременно. Например, если хранимая процедура формирует временную таблицу с именованным ограничением первичного ключа, то она не может быть выполнена несколькими пользователями одновременно.
Глобальные временные таблицы (база данных SQL Azure) в области базы данных
Глобальные временные таблицы для SQL Server (с префиксом ##) хранятся в tempdb и являются общими для всех сеансов пользователей на всем экземпляре SQL Server. Дополнительную информацию о типах таблиц SQL см. в предыдущем разделе о создании таблиц.
База данных SQL Azure поддерживает глобальные временные таблицы, которые хранятся в базе данных tempdb и областью действия которых является база данных. Это означает, что глобальные временные таблицы используются для всех сеансов пользователей в одном База данных SQL Azure. Сеансы пользователей, связанные с другими базами данных, не имеют доступа к глобальным временным таблицам.
Глобальные временные таблицы для База данных SQL Azure соответствуют тому же синтаксису и семантике, что и SQL Server для временных таблиц. Аналогичным образом глобальные временные хранимые процедуры также область уровня базы данных в База данных SQL Azure. Локальные временные таблицы (с префиксом #) также поддерживаются базой данных SQL Azure и имеют тот же синтаксис и семантику, что и на SQL Server. См. предыдущий раздел Временные таблицы.
Эта функция доступна для База данных SQL Azure.
Устранение неполадок с глобальными временными таблицами в Базе данных SQL Azure
Сведения об устранении неполадок с базой данных tempdb см. в разделе Мониторинг использования базы данных tempdb.
Только администратор сервера может получить доступ к динамическим представлениям по устранению неполадок в База данных SQL Azure.
Разрешения
Любой пользователь может создавать глобальные временные объекты. Если не предоставлены какие-либо дополнительные разрешения, то пользователи могут производить доступ только к тем объектам, которыми они владеют.
Секционированные таблицы
Перед созданием секционированной таблицы с помощью инструкции CREATE TABLE следует вначале создать функцию секционирования, чтобы указать, как должна быть секционирована таблица. Функция секционирования создается с помощью инструкции CREATE PARTITION FUNCTION. Затем необходимо создать схему секционирования, чтобы указать файловые группы, которые будут содержать указанные функцией секционирования секции. Схема секционирования создается с помощью инструкции CREATE PARTITION SCHEME. Для секционированных таблиц нельзя указать ограничения PRIMARY KEY или UNIQUE для разделения файловых групп. Дополнительные сведения см. в разделе Partitioned Tables and Indexes.
Ограничения PRIMARY KEY
- В таблице возможно наличие только одного ограничения по первичному ключу.
- Индекс, формируемый ограничением PRIMARY KEY, не может привести к выходу количества индексов в таблице за пределы в 999 некластеризованных индексов и 1 кластеризованный.
- Если для ограничения PRIMARY KEY не указан параметр CLUSTERED или NONCLUSTERED, применяется параметр CLUSTERED, если для ограничения UNIQUE не определено кластеризованных индексов.
- Все столбцы с ограничением PRIMARY KEY должны иметь признак NOT NULL. Если допустимость значения NULL не указана, то для всех столбцов c ограничением PRIMARY KEY устанавливается признак NOT NULL.
Примечание. В таблицах, оптимизированных для памяти, допускается ключевой столбец, способный принимать значение NULL.
Ограничения UNIQUE
- Если для ограничения UNIQUE не указан параметр CLUSTERED или NONCLUSTERED, по умолчанию применяется параметр NONCLUSTERED.
- Каждое ограничение уникальности создает индекс. Количество ограничений UNIQUE не может привести к выходу количества индексов в таблице за пределы в 999 некластеризованных индексов и 1 кластеризованный.
- Если ограничение уникальности определено на столбце определяемого пользователем типа данных CLR, реализация этого типа должна поддерживать двоичную сортировку или сортировку на основе оператора. Дополнительные сведения об определяемых пользователем типах данных CLR см. в разделе Определяемые пользователем типы данных CLR.
Ограничения FOREIGN KEY
- Если столбцу, имеющему ограничение внешнего ключа, задается значение, отличное от NULL, такое же значение должно существовать и в указываемом столбце; в противном случае будет возвращено сообщение о нарушении внешнего ключа.
- Если не указаны исходные столбцы, ограничения FOREIGN KEY применяются к предшествующему столбцу.
- Ограничения FOREIGN KEY могут ссылаться только на таблицы в пределах той же базы данных на том же сервере. Межбазовую ссылочную целостность необходимо реализовать посредством триггеров. Дополнительные сведения см. в статье об инструкции CREATE TRIGGER.
- Ограничения FOREIGN KEY могут ссылаться на другие столбцы той же таблицы. Это называется самовызовом.
- Предложение REFERENCES ограничения внешнего ключа на уровне столбца может содержать только один ссылочный столбец. Этот столбец должен принадлежать к тому же типу данных, что и столбец, для которого определяется ограничение.
- Предложение 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, все действия CASCADE, SET NULL и SET DEFAULT применяются перед ядро СУБД проверка для любых действий NO ACTION.
- Компонент Database Engine не имеет стандартного предела на количество ограничений FOREIGN KEY, содержащихся в таблице, ссылающейся на другие таблицы, или на количество ограничений FOREIGN KEY в других таблицах, ссылающихся на указанную таблицу. Тем не менее фактическое количество ограничений FOREIGN KEY, доступных для использования, ограничивается конфигурацией оборудования, базы данных и приложения. Рекомендуется, чтобы таблица содержала не более 253 ограничений FOREIGN KEY, а также чтобы на нее ссылалось не более 253 ограничений FOREIGN KEY. Предел эффективности в конкретном случае может более или менее зависеть от приложения и оборудования. При разработке базы данных и приложений следует учитывать стоимость принудительных ограничений FOREIGN KEY.
- Ограничения FOREIGN KEY не применяются к временным таблицам.
- Ограничения FOREIGN KEY могут ссылаться только на столбцы с ограничениями PRIMARY KEY или UNIQUE в таблице, на которую указывает ссылка, или на столбцы уникального индекса (UNIQUE INDEX) такой таблицы.
- Если внешний ключ определен на столбце определяемого пользователем типа данных CLR, реализация этого типа должна поддерживать двоичную сортировку. Дополнительные сведения об определяемых пользователем типах данных CLR см. в разделе Определяемые пользователем типы данных CLR.
- Столбцы, участвующие в связи по внешнему ключу, должны иметь одинаковую длину и масштаб.
DEFAULT, определения
- Столбец может иметь только определение DEFAULT.
- Ограничение DEFAULT может содержать значения констант, функции, стандартные функции без параметров SQL или значение NULL. В следующей таблице приведены функции без параметров и возвращаемые ими по умолчанию значения в процессе выполнения инструкции INSERT.
Функция без параметров SQL-92 Возвращенное значение CURRENT_TIMESTAMP Текущие дата и время. CURRENT_USER Имя пользователя, выполняющего вставку. SESSION_USER Имя пользователя, выполняющего вставку. SYSTEM_USER Имя пользователя, выполняющего вставку. Пользователь Имя пользователя, выполняющего вставку. - Выражение constant_expression в определении DEFAULT не может ссылаться на другой столбец таблицы, а также на другие таблицы, представления или хранимые процедуры.
- Определения DEFAULT нельзя создавать для столбцов с типом данных timestamp или столбцов со свойством IDENTITY.
- Определения DEFAULT нельзя создавать для столбцов с псевдонимами типов данных, если такой тип привязан к определенному по умолчанию объекту.
CHECK, ограничение
- Столбец может содержать любое количество ограничений CHECK, а условие может включать несколько логических выражений, соединенных операторами AND и OR. При указании нескольких ограничений CHECK для столбца их проверка производится в порядке создания.
- Условие поиска должно возвращать логическое выражение и не может ссылаться на другую таблицу.
- Ограничение CHECK уровня столбца может ссылаться только на ограничиваемый столбец, а ограничение CHECK уровня таблицы — только на столбцы этой таблицы. Правила и ограничения CHECK выполняют одну и ту же функцию проверки данных при выполнении инструкций INSERT и UPDATE.
- Если для столбца или столбцов задано правило либо одно или несколько ограничений CHECK, применяются все ограничения.
- Ограничения CHECK нельзя определять для столбцов типов text, ntext или image.
Дополнительные сведения об ограничении
- Индекс, созданный для ограничения, нельзя удалить с помощью инструкции DROP INDEX . Вам нужно удалить ограничение с помощью инструкции ALTER TABLE . Индекс, созданный для ограничения и используемый им, можно перестроить с помощью инструкции ALTER INDEX . REBUILD . Дополнительные сведения см. в статье Реорганизация и перестроение индексов.
- Имена ограничений должны подчиняться правилам для идентификаторов, за исключением тех, которые не могут начинаться с символа решетки (#). Если аргумент constraint_name не указан, то ограничению присваивается имя, формируемое системой. Имя ограничения отображается в любых сообщениях об ошибках, связанных с нарушением ограничения.
- При нарушении ограничения в инструкции INSERT , UPDATE или DELETE выполнение инструкции прекращается. Однако если параметр SET XACT_ABORT установлен в значение OFF, а инструкция является частью явной транзакции, выполнение этой транзакции продолжается. Если параметр SET XACT_ABORT установлен в значение ON, производится откат всей транзакции. С определением транзакции можно также использовать инструкцию ROLLBACK TRANSACTION , установив флажок для системной функции @@ERROR .
- Когда присвоены значения ALLOW_ROW_LOCKS = ON и ALLOW_PAGE_LOCK = ON , при доступе к индексу допустимы блокировки на уровне строк, страниц и таблиц. Ядро СУБД выбирает соответствующую блокировку и может передавать блокировку из строки или блокировки страницы на блокировку таблицы. Если присвоены значения ALLOW_ROW_LOCKS = OFF и ALLOW_PAGE_LOCK = OFF , при доступе к индексу допустима только блокировка на уровне таблиц.
- Если в таблице содержатся ограничения FOREIGN KEY или CHECK и триггеры, условия ограничений вычисляются перед выполнением триггера.
Получить отчет о таблице и ее столбцах можно с помощью процедуры sp_help или sp_helpconstraint . Для переименования таблицы используется процедура sp_rename . Чтобы получить сведения о представлениях и хранимых процедурах, зависящих от таблицы, используйте функции sys.dm_sql_referenced_entities и sys.dm_sql_referencing_entities.
Правила допустимости значения NULL в рамках определения таблицы
Допустимость значений NULL для столбца определяет, разрешает ли столбец использовать такие значения для своих данных. Значение NULL не является нулевым или пустым. NULL означает, что никаких данных не вводилось либо значение NULL было указано явно. Обычно оно подразумевает, что значение неизвестно или неприменимо.
При создании или изменении таблицы с помощью инструкции CREATE TABLE или ALTER TABLE параметры базы данных и сеанса влияют на допустимость значений NULL для типа данных, указанного в определении столбца, и могут переопределять ее. Рекомендуется всегда явно определять столбец как NULL или NOT NULL для невычисляемых столбцов или, если используется пользовательский тип данных, разрешать, чтобы для столбца применялась возможность, установленная для этого типа по умолчанию. Для разреженных столбцов всегда должно быть разрешено значение NULL.
Если возможность столбца принимать значение NULL не задана явно, она определяется согласно правилам, указанным в следующей таблице.
Если настроены какие-либо параметры базы данных с помощью инструкции ALTER DATABASE :
ANSI_NULL_DEFAULT_ON = ON , присваивается значение NULL.
ANSI_NULL_DEFAULT_OFF = ON , присваивается значение NOT NULL.Если для сеанса не установлен ни один из параметров ANSI_NULL_DFLT, а база данных настроена по умолчанию (ANSI_NULL_DEFAULT = OFF), применяется установленное по умолчанию значение NOT NULL.
Если столбец является вычисляемым столбцом, его значение NULL всегда определяется автоматически ядро СУБД. Определить допустимость значения NULL для этого типа столбцов можно с помощью функции COLUMNPROPERTY со свойством AllowsNull.
Как драйвер ODBC для SQL Server, так и драйвер OLE DB для SQL Server предусматривают по умолчанию значение параметра ANSI_NULL_DFLT_ON, равное ON. Пользователи ODBC и OLE DB могут настраивать этот параметр в источниках данных ODBC или с помощью установки атрибутов или свойств соединения в приложении.
Сжатие данных
В системных таблицах не может быть включено сжатие. При создании таблицы параметру сжатия данных присваивается значение NONE, если не указано иное. При указании списка секций или секции, выходящей за пределы диапазона, будет сформирована ошибка. Дополнительную информацию о сжатии данных см. в разделе Сжатие данных.
Оценить состояние сжатия таблицы, индекса или секции можно с помощью хранимой процедуры sp_estimate_data_compression_savings.
Разрешения
Требуется разрешение CREATE TABLE в базе данных и разрешение ALTER для схемы, в которой создается таблица.
Если какие-либо столбцы в инструкции CREATE TABLE определены как принадлежащие к пользовательскому типу, необходимо иметь разрешение REFERENCES для этого типа.
Если какие-либо столбцы в инструкции CREATE TABLE определены как принадлежащие к определяемому пользователем типу данных CLR, необходимо быть владельцем этого типа либо иметь разрешение REFERENCES для него.
Если какие-либо столбцы в инструкции CREATE TABLE имеют связанную коллекцию схем XML, необходимо быть владельцем этой коллекции схем или иметь разрешение REFERENCES для нее.
Временные таблицы в базе данных tempdb может создавать любой пользователь.
Если инструкция создает таблицу реестра, требуется разрешение ENABLE LEDGER .
Примеры
А. Создание ограничения PRIMARY KEY для столбца
В следующем примере показано определение ограничения PRIMARY KEY с кластеризованным индексом для столбца EmployeeID таблицы Employee . Поскольку имя ограничения не указано, оно будет подставлено системой.
CREATE TABLE dbo.Employee ( EmployeeID INT PRIMARY KEY CLUSTERED );B. Применение ограничений FOREIGN KEY
Ограничение FOREIGN KEY используется для ссылки на другую таблицу. Внешние ключи могут включать один или несколько столбцов. В следующем примере показано ограничение FOREIGN KEY с одним столбцом в таблице SalesOrderHeader , ссылающееся на таблицу SalesPerson . Для ограничения FOREIGN KEY с одним столбцом требуется только предложение REFERENCES.
SalesPersonID INT NULL REFERENCES SalesPerson(SalesPersonID)Кроме того, предложение FOREIGN KEY можно применить явно и заново определить атрибут столбца. Имена столбцов в обеих таблицах могут различаться.
FOREIGN KEY (SalesPersonID) REFERENCES SalesPerson(SalesPersonID)Ограничения по ключам с несколькими столбцами создаются в виде табличных ограничений. В базе данных AdventureWorks2022 таблица SpecialOfferProduct включает ограничение PRIMARY KEY с несколькими столбцами. В следующем примере показано, как обращаться к этому ключу из другой таблицы; задавать имя ограничения явно необязательно.
CONSTRAINT FK_SpecialOfferProduct_SalesOrderDetail FOREIGN KEY (ProductID, SpecialOfferID) REFERENCES SpecialOfferProduct (ProductID, SpecialOfferID)C. Применение ограничений UNIQUE
Ограничения UNIQUE используются для указания уникальности непервичных ключевых столбцов. В следующем примере применяется ограничение уникальности столбца Name таблицы Product .
Name NVARCHAR(100) NOT NULL UNIQUE NONCLUSTEREDD. Применение определений DEFAULT
Определения DEFAULT (вместе с инструкциями INSERT и UPDATE) позволяют указать значение по умолчанию, используемое, если значение не задано. Например, база данных AdventureWorks2022 может включать таблицу уточняющих запросов, содержащую различные должности, которые могут занимать сотрудники компании. В столбце, описывающем каждую должность, значение символьной строки по умолчанию может содержать описание, отображаемое, если фактическое описание должности не было введено явно.
DEFAULT 'New Position - title not formalized yet'Кроме констант, определения DEFAULT могут включать функции. Следующий пример позволяет получить текущую дату для той или иной записи.
DEFAULT (GETDATE())Обработка функциями без параметров также может повысить целостность данных. Чтобы определить пользователя, вставившего строку, используйте функцию без параметров для USER. Не заключайте функции без параметров в скобки.
DEFAULT USERД. Применение ограничений CHECK
В следующем примере показано ограничение, применяемое к значениям, вводимым в столбец CreditRating таблицы Vendor . Ограничение не имеет имени.
CHECK (CreditRating >= 1 and CreditRatingВ этом примере показано именованное ограничение вводимых в столбец таблицы символьных данных по шаблону.
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. Вывод на экран полного определения таблицы
В следующем примере выводятся полные определения таблицы со всеми определениями ограничений для таблицы PurchaseOrderDetail , созданной в базе данных AdventureWorks2022 . Для выполнения этого образца схема таблицы заменяется на схему 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 HRResumeSchemaCollection . Ключевое слово DOCUMENT указывает, что каждый экземпляр типа данных xml в столбце column_name может содержать только один элемент верхнего уровня.
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Секции назначаются на основе столбца col1 таблицы PartitionTable следующими способами.
Файловая группа test1fg test2fg test3fg test4fg Секция 1 2 3 4 Значения col 1 col1 > 1 AND col1 col1 > 100 AND col1 col1 > 1000 I. Использование типа данных UNIQUEIDENTIFIER в столбце
В следующем примере создается таблица со столбцом типа uniqueidentifier . В этом примере используется ограничение PRIMARY KEY для защиты таблицы от вставки пользователями повторяющихся значений, а также функция NEWSEQUENTIALID() в ограничении DEFAULT для указания значений для новых строк. К столбцу uniqueidentifier применяется свойство ROWGUIDCOL, чтобы на столбец можно было ссылаться с помощью ключевого слова $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) );J. Использование выражения для вычисляемого столбца
В следующем примере показано использование выражения ( (low + high)/2 ) для вычисления столбца myavg .
CREATE TABLE dbo.mytable ( low INT, high INT, myavg AS (low + high)/2 );K. Создание вычисляемого столбца на основе столбца определяемого пользователем типа
В следующем примере создается таблица с одним столбцом, имеющим определяемый пользовательским тип utf8string , и предполагается, что как сборка, содержащая данный тип, так и сам тип, уже созданы в текущей базе данных. Второй столбец определяется на основе типа utf8string и использует метод ToString() типа type(class) utf8string для вычисления значения столбца.
CREATE TABLE UDTypeTable ( u UTF8STRING, ustr AS u.ToString() PERSISTED );L. Использование функции USER_NAME для вычисляемого столбца
В следующем примере используется функция USER_NAME() в столбце myuser_name .
CREATE TABLE dbo.mylogintable ( date_in DATETIME, user_id INT, myuser_name AS USER_NAME() );M. Создание таблицы со столбцом FILESTREAM
В следующем примере создается таблица со столбцом FILESTREAM Photo . Если таблица содержит один или более столбцов FILESTREAM , она должна содержать столбец ROWGUIDCOL .
CREATE TABLE dbo.EmployeePhoto ( EmployeeId INT NOT NULL PRIMARY KEY, Photo VARBINARY(MAX) FILESTREAM NULL, MyRowGuidColumn UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE DEFAULT NEWID() );О. Создание таблицы, использующей сжатие строк
В следующем примере создается таблица, использующая сжатие строк.
CREATE TABLE dbo.T1 ( c1 INT, c2 NVARCHAR(200) ) WITH (DATA_COMPRESSION = ROW);Дополнительные примеры сжатия данных см. в разделе Сжатие данных.
O. Создание таблицы, использующей сжатие XML
Область применения: SQL Server 2022 (16.x) и более поздних версий, База данных SQL Azure и Управляемый экземпляр SQL Azure.
В следующем примере создается таблица, использующая сжатие XML.
CREATE TABLE dbo.T1 ( c1 INT, c2 XML ) WITH (XML_COMPRESSION = ON);P. Создание таблицы с разреженными столбцами и набором столбцов
В следующих примерах показано создание таблицы с разреженным столбцом и таблицы с двумя разреженными столбцами и набором столбцов. В примерах используется основной синтаксис. Более сложные примеры см. в разделе Использование разреженных столбцов и Использование наборов столбцов.
В следующем примере создается таблица с разреженным столбцом.
CREATE TABLE dbo.T1 ( c1 INT PRIMARY KEY, c2 VARCHAR(50) SPARSE NULL );В этом примере создается таблица с двумя разреженными столбцами и набором столбцов с именем CSet .
CREATE TABLE T1 ( c1 INT PRIMARY KEY, c2 VARCHAR(50) SPARSE NULL, c3 INT SPARSE NULL, CSet XML COLUMN_SET FOR ALL_SPARSE_COLUMNS );В. Создание темпоральной таблицы на основе диска с системным управлением версиями
Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure.
В следующих примерах показано, как создать темпоральную таблицу, привязанную к новой таблице журнала, и как создать темпоральную таблицу, привязанную к существующей таблице журнала. Для темпоральной таблицы должен быть определен первичный ключ, чтобы включить системное управление версиями. Примеры добавления или удаления системного управления версиями в существующей таблице см. в главе Примеры в разделе "Системное управление версиями". Варианты использования описаны в разделе Темпоральные таблицы.
В этом примере создается новая темпоральная таблица, привязанная к новой таблице журнала.
CREATE TABLE Department ( DepartmentNumber CHAR(10) NOT NULL PRIMARY KEY CLUSTERED, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH (SYSTEM_VERSIONING = ON);В этом примере создается новая темпоральная таблица, привязанная к существующей таблице журнала.
-- Existing table CREATE TABLE Department_History ( DepartmentNumber CHAR(10) NOT NULL, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 NOT NULL, ValidTo DATETIME2 NOT NULL ); -- Temporal table CREATE TABLE Department ( DepartmentNumber CHAR(10) NOT NULL PRIMARY KEY CLUSTERED, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Department_History, DATA_CONSISTENCY_CHECK = ON));R. Создание оптимизированной для памяти темпоральной таблицы с системным управлением версиями
Область применения: SQL Server 2016 (13.x) и более поздние версии, а также База данных SQL Azure.
В следующем примере показано, как создать оптимизированную для памяти темпоральную таблицу с системным управлением версиями, привязанную к новой таблице журнала на диске.
В этом примере создается новая темпоральная таблица, привязанная к новой таблице журнала.
CREATE SCHEMA History; GO CREATE TABLE dbo.Department ( DepartmentNumber CHAR(10) NOT NULL PRIMARY KEY NONCLUSTERED, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA, SYSTEM_VERSIONING = ON (HISTORY_TABLE = History.DepartmentHistory) );В этом примере создается новая темпоральная таблица, привязанная к существующей таблице журнала.
-- Existing table CREATE TABLE Department_History ( DepartmentNumber CHAR(10) NOT NULL, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 NOT NULL, ValidTo DATETIME2 NOT NULL ); -- Temporal table CREATE TABLE Department ( DepartmentNumber CHAR(10) NOT NULL PRIMARY KEY CLUSTERED, DepartmentName VARCHAR(50) NOT NULL, ManagerID INT NULL, ParentDepartmentNumber CHAR(10) NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Department_History, DATA_CONSISTENCY_CHECK = ON) );S. Создание таблицы с зашифрованными столбцами
В следующем примере создается таблица с двумя зашифрованными столбцами. Дополнительные сведения см. в разделе Постоянное шифрование.
CREATE TABLE Customers ( CustName NVARCHAR(60) ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = MyCEK, ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ), SSN VARCHAR(11) COLLATE Latin1_General_BIN2 ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = MyCEK, ENCRYPTION_TYPE = DETERMINISTIC , ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ), Age INT NULL );T. Создание встроенного фильтруемого индекса
В этом примере создается таблица со встроенным фильтруемым индексом.
CREATE TABLE t1 ( c1 INT, index IX1 (c1) WHERE c1 > 0 );Ф. Создание встроенного индекса
В приведенном ниже примере показано использование встроенного параметра NONCLUSTERED для дисковых таблиц.
CREATE TABLE t1 ( c1 INT, INDEX ix_1 NONCLUSTERED (c1) ); CREATE TABLE t2 ( c1 INT, c2 INT INDEX ix_1 NONCLUSTERED ); CREATE TABLE t3 ( c1 INT, c2 INT, INDEX ix_1 NONCLUSTERED (c1,c2) );V. Создание временной таблицы с анонимным составным первичным ключом.
В примере создается таблица с анонимным составным первичным ключом. Это полезно для предотвращения конфликтов во время выполнения, если две временные таблицы, областью действия которых являются сеансы (каждая в отдельном сеансе), используют одно и то же имя для ограничения.
CREATE TABLE #tmp ( c1 INT, c2 INT, PRIMARY KEY CLUSTERED ([c1], [c2]) ); GOЕсли вы явным образом именуете ограничение, во втором сеансе возникнет ошибка, например:
Msg 2714, Level 16, State 5, Line 1 There is already an object named 'PK_#tmp' in the database. Msg 1750, Level 16, State 1, Line 1 Could not create constraint or index. See previous errors.Причина проблемы в том, что имя временной таблицы уникально, а имена ограничений — нет.
Ц. Использование глобальных временных таблиц в базе данных SQL Azure
Сеанс A создает глобальную временную таблицу ##test в базе данных SQL Azure testdb1 и добавляет одну строку
CREATE TABLE ##test ( a INT, b INT ); INSERT INTO ##test VALUES (1, 1); -- Obtain object ID for temp table ##test SELECT OBJECT_ID('tempdb.dbo.##test') AS 'Object ID';1253579504Получаем имя глобальной временной таблицы для идентификатора объекта 1253579504 в tempdb (2)
SELECT name FROM tempdb.sys.objects WHERE object_id = 1253579504;##testСеанс B подключается к базе данных SQL Azure testdb1 и может открыть таблицу ##test, созданную сеансом A
SELECT * FROM ##test;Сеанс C подключается к другой базе данных SQL Azure testdb2 и хочет получить доступ к таблице ##test, созданной в базе данных testdb1. Это невозможно, поскольку глобальные временные таблицы существуют в области базы данных
SELECT * FROM ##testВ результате выдается следующая ошибка:
Msg 208, Level 16, State 0, Line 1 Invalid object name '##test'Обращение к системному объекту в базе данных SQL Azure tempdb из текущей базы данных пользователя testdb1
SELECT * FROM tempdb.sys.objects; SELECT * FROM tempdb.sys.columns; SELECT * FROM tempdb.sys.database_files;.X Включение политики хранения данных в таблице
В следующем примере создается таблица с включенным хранением данных и периодом хранения, равным одной неделе. Этот пример применяется только к SQL Azure для пограничных вычислений.
CREATE TABLE [dbo].[data_retention_table] ( [dbdatetime2] datetime2(7), [product_code] int, [value] char(10) ) WITH (DATA_DELETION = ON ( FILTER_COLUMN = [dbdatetime2], RETENTION_PERIOD = 1 WEEKS ))Y. Создание обновляемой таблицы реестра
В следующем примере создается обновляемая таблица реестра, которая не является темпоральной таблицей, с анонимной таблицей журнала (имя таблицы журнала система создает автоматически) и создаваемым именем представления реестра. Так как для обязательных столбцов GENERATED ALWAYS имена не указаны, и дополнительные столбцы в представлении реестра не определены, будут использоваться имена столбцов по умолчанию.
CREATE SCHEMA [HR]; GO CREATE TABLE [HR].[Employees] ( EmployeeID INT NOT NULL, Salary Money NOT NULL ) WITH (SYSTEM_VERSIONING = ON, LEDGER = ON); GOВ следующем примере создается таблица, которая одновременно является темпоральной таблицей и обновляемой таблицей реестра, с анонимной таблицей журнала (имя для таблицы журнала система создает автоматически) и создаваемым именем представления реестра. Для столбцов GENERATED ALWAYS и дополнительных столбцов представления реестра используются имена по умолчанию.
CREATE SCHEMA [HR]; GO CREATE TABLE [HR].[Employees] ( EmployeeID INT NOT NULL PRIMARY KEY, Salary Money NOT NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH (SYSTEM_VERSIONING = ON, LEDGER = ON); GOВ следующем примере создается таблица, которая одновременно является темпоральной таблицей и обновляемой таблицей реестра, с явно именованной таблицей журнала, заданными пользователем именами для столбцов GENERATED ALWAYS и дополнительными столбцами в представлении реестра.
CREATE SCHEMA [HR]; GO CREATE TABLE [HR].[Employees] ( EmployeeID INT NOT NULL PRIMARY KEY, Salary Money NOT NULL, StartTransactionId BIGINT GENERATED ALWAYS AS TRANSACTION_ID START HIDDEN NOT NULL, EndTransactionId BIGINT GENERATED ALWAYS AS TRANSACTION_ID END HIDDEN NULL, StartSequenceNumber BIGINT GENERATED ALWAYS AS SEQUENCE_NUMBER START HIDDEN NOT NULL, EndSequenceNumber BIGINT GENERATED ALWAYS AS SEQUENCE_NUMBER END HIDDEN NULL, ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = [HR].[EmployeesHistory]), LEDGER = ON ( LEDGER_VIEW = [HR].[EmployeesLedger] ( TRANSACTION_ID_COLUMN_NAME = TransactionId, SEQUENCE_NUMBER_COLUMN_NAME = SequenceNumber, OPERATION_TYPE_COLUMN_NAME = OperationId, OPERATION_TYPE_DESC_COLUMN_NAME = OperationTypeDescription ) ) ); GOВ следующем примере создается таблица реестра только для добавления с созданными именами представления реестра и столбцами в представлении реестра.
CREATE SCHEMA [AccessControl]; GO CREATE TABLE [AccessControl].[KeyCardEvents] ( EmployeeID INT NOT NULL, AccessOperationDescription NVARCHAR (MAX) NOT NULL, [Timestamp] Datetime2 NOT NULL, StartTransactionId BIGINT GENERATED ALWAYS AS TRANSACTION_ID START HIDDEN NOT NULL, StartSequenceNumber BIGINT GENERATED ALWAYS AS SEQUENCE_NUMBER START HIDDEN NOT NULL ) WITH ( LEDGER = ON ( LEDGER_VIEW = [AccessControl].[KeyCardEventsLedger] ( TRANSACTION_ID_COLUMN_NAME = TransactionId, SEQUENCE_NUMBER_COLUMN_NAME = SequenceNumber, OPERATION_TYPE_COLUMN_NAME = OperationId, OPERATION_TYPE_DESC_COLUMN_NAME = OperationTypeDescription ), APPEND_ONLY = ON ) ); GOВ следующем примере создается база данных реестра в Базе данных SQL Azure и обновляемая таблица реестра с параметрами по умолчанию. Для создания обновляемой таблицы реестра в базе данных реестра не требуется использовать WITH (SYSTEM_VERSIONING = ON, LEDGER = ON); .
CREATE DATABASE MyLedgerDB ( EDITION = 'GeneralPurpose' ) WITH LEDGER = ON; GO CREATE SCHEMA [HR]; GO CREATE TABLE [HR].[Employees] ( EmployeeID INT NOT NULL, Salary Money NOT NULL ) GOСледующие шаги
- ALTER TABLE
- COLUMNPROPERTY
- CREATE INDEX
- CREATE VIEW
- Data Types
- DROP INDEX
- sys.dm_sql_referenced_entities
- sys.dm_sql_referencing_entities
- DROP TABLE
- CREATE PARTITION FUNCTION
- CREATE PARTITION SCHEME
- CREATE TYPE
- EVENTDATA
- sp_help
- sp_helpconstraint
- sp_rename
- sp_spaceused
