CREATE DOMAIN
CREATE DOMAIN — создать домен
Синтаксис
CREATE DOMAINимя
[ AS ]тип_данных
[ COLLATEправило_сортировки
] [ DEFAULTвыражение
] [ограничение
[ ... ] ] Здесьограничение
: [ CONSTRAINTимя_ограничения
] { NOT NULL | NULL | CHECK (выражение
) }
Описание
CREATE DOMAIN
создаёт новый домен. Домен по сути представляет собой тип данных с дополнительными условиями (ограничивающими допустимый набор значений). Владельцем домена становится пользователь его создавший.
Если задаётся имя схемы (например, CREATE DOMAIN myschema.mydomain ...
), домен создаётся в указанной схеме, в противном случае — в текущей. Имя домена должно быть уникальным среди имён типов и доменов, существующих в этой схеме.
Домены полезны для абстрагирования и вынесения общих характеристик разных полей в единое место для упрощения сопровождения. Например, в нескольких таблицах может присутствовать столбец, содержащий электронный адрес, и для всех требуются одинаковые ограничения CHECK, проверяющие синтаксис адреса. В этом случае лучше определить домен, а не задавать для каждой таблицы отдельные ограничения.
Чтобы создать домен, необходимо иметь право USAGE
для нижележащего типа.
Параметры
имя
Имя создаваемого домена (возможно, дополненное схемой).
тип_данных
Нижележащий тип данных домена (может включать определение массива с этим типом).
правило_сортировки
Необязательное указание правила сортировки для домена. Если это указание отсутствует, в домене используется правило сортировки нижележащего типа данных. Указать
COLLATE
можно, только если нижележащий тип данных является сортируемым.DEFAULT
выражение
Предложение
DEFAULT
определяет значение по умолчанию для столбцов, типом данных которых является этот домен. Значением может быть любое выражение без переменных (подзапросы также не допускаются). Тип данных этого выражения должен соответствовать типу данных домена. Если значение по умолчанию не указано, им будет значение NULL.Значение по умолчанию будет использоваться в любой операции добавления строк, в которой не задано значение для этого столбца. Если значение по умолчанию установлено для конкретного столбца, оно будет переопределять значение по умолчанию, связанное с доменом. В свою очередь, значение по умолчанию для домена переопределяет любое значение по умолчанию, связанное с нижележащим типом данных.
CONSTRAINT
имя_ограничения
Имя ограничения. Если не указано явно, имя будет сгенерировано системой.
NOT NULL
Значения этого домена будут отличны от NULL (но см. замечания ниже).
NULL
Этот домен может содержать значение NULL. Это свойство домена по умолчанию.
Это предложение предназначено только для совместимости с нестандартными базами данных SQL. Использовать его в новых приложениях не рекомендуется.
CHECK (
выражение
)Предложения
CHECK
задают ограничения целостности или проверки, которым должны удовлетворять значения домена. Каждое ограничение должно представлять собой выражение, выдающее результат типа Boolean. Проверяемое значение в этом выражении обозначается ключевым словомVALUE
. Если выражение выдаёт FALSE, сообщается об ошибке и приведение значения к типу домена запрещается.В настоящее время выражения
CHECK
не могут содержать переменные, кромеVALUE
, и подзапросы.Когда для домена задано несколько ограничений
CHECK
, они будут проверяться в алфавитном порядке имён. (До версии 9.5 в PostgreSQL не было установлено никакого определённого порядка обработки ограниченийCHECK
.)
Примечания
Ограничения домена, в частности NOT NULL
, проверяются при преобразовании значения к типу домена. Однако из столбца, который номинально имеет тип домена, всё же можно прочитать NULL, несмотря на такое ограничение. Например, это может происходить в запросе внешнего соединения, если столбец домена окажется в обнуляемой стороне внешнего соединения. Более тонкий пример:
INSERT INTO tab (domcol) VALUES ((SELECT domcol FROM tab WHERE false));
Пустой скалярный вложенный SELECT выдаст значение NULL, типом которого будет считаться домен, так что к этому значению не будут применены дополнительные проверки ограничений и строка будет успешно добавлена.
Избежать таких проблем очень сложно, так как в SQL вообще предполагается, что значение NULL является подходящим для любого типа данных. Таким образом, лучше всего разрабатывать ограничения так, чтобы значения NULL допускались, а затем при необходимости применять ограничения NOT NULL
к столбцам доменного типа, а не непосредственно к самому этому типу.
В Postgres Pro предполагается, что условия ограничений CHECK
являются постоянными, то есть при одинаковых входных значениях они всегда выдают одинаковый результат. Именно этим предположением оправдывается то, что ограничения CHECK
проверяются только при первом преобразовании значения в тип домена, а не при каждом обращении к нему. (По сути таким же образом обрабатываются ограничения CHECK
для таблиц, как описано в Подразделе 5.4.1.)
Однако это предположение может нарушаться, как часто бывает, когда в выражении CHECK
используется пользовательская функция, поведение которой впоследствии меняется. Postgres Pro не запрещает этого, и если сохранённые значения типа домена перестанут удовлетворять ограничению CHECK
, это останется незамеченным. В итоге при попытке загрузить выгруженные позже данные могут возникнуть проблемы. Поэтому подобные изменения рекомендуется осуществлять следующим образом: удалить ограничение (используя ALTER DOMAIN
), изменить определение функции, а затем пересоздать ограничение той же командой, которая при этом перепроверит сохранённые данные.
Примеры
В этом примере создаётся тип данных us_postal_code
(почтовый индекс США), который затем используется в определении таблицы. Для проверки значения на соответствие формату почтовых индексов США применяется проверка с регулярными выражениями:
CREATE DOMAIN us_postal_code AS TEXT CHECK( VALUE ~ '^\d{5}$' OR VALUE ~ '^\d{5}-\d{4}$' ); CREATE TABLE us_snail_addy ( address_id SERIAL PRIMARY KEY, street1 TEXT NOT NULL, street2 TEXT, street3 TEXT, city TEXT NOT NULL, postal us_postal_code NOT NULL );
Совместимость
Команда CREATE DOMAIN
соответствует стандарту SQL.
См. также
ALTER DOMAIN, DROP DOMAINCLUSTER
CLUSTER — cluster a table according to an index
Synopsis
CLUSTER [ (option
[, ...] ) ] [table_name
[ USINGindex_name
] ] whereoption
can be one of: VERBOSE [boolean
]
Description
CLUSTER
instructs Postgres Pro to cluster the table specified by table_name
based on the index specified by index_name
. The index must already have been defined on table_name
.
When a table is clustered, it is physically reordered based on the index information. Clustering is a one-time operation: when the table is subsequently updated, the changes are not clustered. That is, no attempt is made to store new or updated rows according to their index order. (If one wishes, one can periodically recluster by issuing the command again. Also, setting the table's fillfactor
storage parameter to less than 100% can aid in preserving cluster ordering during updates, since updated rows are kept on the same page if enough space is available there.)
When a table is clustered, Postgres Pro remembers which index it was clustered by. The form CLUSTER
reclusters the table using the same index as before. You can also use the table_name
CLUSTER
or SET WITHOUT CLUSTER
forms of ALTER TABLE
to set the index to be used for future cluster operations, or to clear any previous setting.
CLUSTER
without a table_name
reclusters all the previously-clustered tables in the current database that the calling user has privileges for. This form of CLUSTER
cannot be executed inside a transaction block.
When a table is being clustered, an ACCESS EXCLUSIVE
lock is acquired on it. This prevents any other database operations (both reads and writes) from operating on the table until the CLUSTER
is finished.
Parameters
table_name
The name (possibly schema-qualified) of a table.
index_name
The name of an index.
VERBOSE
Prints a progress report as each table is clustered.
boolean
Specifies whether the selected option should be turned on or off. You can write
TRUE
,ON
, or1
to enable the option, andFALSE
,OFF
, or0
to disable it. Theboolean
value can also be omitted, in which caseTRUE
is assumed.
Notes
To cluster a table, one must have the MAINTAIN
privilege on the table.
In cases where you are accessing single rows randomly within a table, the actual order of the data in the table is unimportant. However, if you tend to access some data more than others, and there is an index that groups them together, you will benefit from using CLUSTER
. If you are requesting a range of indexed values from a table, or a single indexed value that has multiple rows that match, CLUSTER
will help because once the index identifies the table page for the first row that matches, all other rows that match are probably already on the same table page, and so you save disk accesses and speed up the query.
CLUSTER
can re-sort the table using either an index scan on the specified index, or (if the index is a b-tree) a sequential scan followed by sorting. It will attempt to choose the method that will be faster, based on planner cost parameters and available statistical information.
While CLUSTER
is running, the search_path is temporarily changed to pg_catalog, pg_temp
.
When an index scan is used, a temporary copy of the table is created that contains the table data in the index order. Temporary copies of each index on the table are created as well. Therefore, you need free space on disk at least equal to the sum of the table size and the index sizes.
When a sequential scan and sort is used, a temporary sort file is also created, so that the peak temporary space requirement is as much as double the table size, plus the index sizes. This method is often faster than the index scan method, but if the disk space requirement is intolerable, you can disable this choice by temporarily setting enable_sort to off
.
It is advisable to set maintenance_work_mem to a reasonably large value (but not more than the amount of RAM you can dedicate to the CLUSTER
operation) before clustering.
Because the planner records statistics about the ordering of tables, it is advisable to run ANALYZE
on the newly clustered table. Otherwise, the planner might make poor choices of query plans.
Because CLUSTER
remembers which indexes are clustered, one can cluster the tables one wants clustered manually the first time, then set up a periodic maintenance script that executes CLUSTER
without any parameters, so that the desired tables are periodically reclustered.
Each backend running CLUSTER
will report its progress in the pg_stat_progress_cluster
view. See Section 26.4.2 for details.
Clustering a partitioned table clusters each of its partitions using the partition of the specified partitioned index. When clustering a partitioned table, the index may not be omitted. CLUSTER
on a partitioned table cannot be executed inside a transaction block.
Examples
Cluster the table employees
on the basis of its index employees_ind
:
CLUSTER employees USING employees_ind;
Cluster the employees
table using the same index that was used before:
CLUSTER employees;
Cluster all tables in the database that have previously been clustered:
CLUSTER;
Compatibility
There is no CLUSTER
statement in the SQL standard.
The following syntax was used before PostgreSQL 17 and is still supported:
CLUSTER [ VERBOSE ] [table_name
[ USINGindex_name
] ]
The following syntax was used before PostgreSQL 8.3 and is still supported:
CLUSTERindex_name
ONtable_name