ALTER TABLE changes the definition of a table. For information on using ALTER TABLE, see the pages for its subcommands.
This schema change statement is registered as a job. You can view long-running jobs with .
Required privileges
Refer to the respective subcommands.Synopsis
alter_table_cmd is:
Parameters
| Parameter | Description |
|---|---|
IF EXISTS | Change the table only if a table with the current name exists; if one does not exist, do not return an error. |
table\_name | The name of the table you want to change. |
Subcommands
| Subcommand | Description | Can combine with other subcommands? |
|---|---|---|
ADD COLUMN | Add columns to tables. | Yes |
ADD CONSTRAINT | Add constraints to columns. | Yes |
ALTER COLUMN | Change an existing column. | Yes |
ALTER PRIMARY KEY | Change the of a table. | Yes |
CONFIGURE ZONE | for a table. | No |
DROP COLUMN | Remove columns from tables. | Yes |
DROP CONSTRAINT | Remove constraints from columns. | Yes |
EXPERIMENTAL\_AUDIT | Enable per-table audit logs, for security purposes. | Yes |
OWNER TO | Change the owner of the table. | No |
PARTITION BY | Partition, re-partition, or un-partition a table. | Yes |
RENAME COLUMN | Change the names of columns. | Yes |
RENAME CONSTRAINT | Change constraints columns. | Yes |
RENAME TO | Change the names of tables. | No |
RESET {storage parameter} | Reset a storage parameter on a table to its default value. | Yes |
SET {storage parameter} | Set a storage parameter on a table. | Yes |
SET LOCALITY | Set the table locality for a table in a . | No |
SET SCHEMA | Change the of a table. | No |
SCATTER | Makes a best-effort attempt to redistribute replicas and leaseholders for the ranges of a table or index. Note that it does not return an error even if replicas are not moved. | No |
SPLIT AT | Force a at the specified row in the table. | No |
UNSPLIT AT | Remove a range split enforcement in the table. | No |
VALIDATE CONSTRAINT | Check whether values in a column match a on the column. | Yes |
ADD COLUMN
Use ALTER TABLE... ADD COLUMN to add columns to existing tables.
For examples, see Add columns.
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
IF NOT EXISTS | Add a column only if a column of the same name does not already exist; if one does exist, do not return an error. |
column\_name | The name of the column you want to add. The column name must follow these and must be unique within the table but can have the same name as indexes or constraints. |
typename | The of the new column. |
col\_qualification | An optional list of . |
ADD CONSTRAINT
Use ALTER TABLE... ADD CONSTRAINT to add the following to columns:
To add a primary key constraint to a table, you should explicitly define the primary key at . To replace an existing primary key, you can use ADD CONSTRAINT... PRIMARY KEY. For details, see Changing primary keys with ADD CONSTRAINT... PRIMARY KEY.
The and constraints are managed through .
For examples, see Add constraints.
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
IF NOT EXISTS | Add a constraint only if a constraint of the same name does not already exist; if one does exist, do not return an error. |
constraint\_name | The name of the constraint, which must be unique to its table and follow these . |
constraint\_elem | The , , or constraint you want to add. Adding/changing a DEFAULT constraint is done through ALTER COLUMN. Adding/changing the table’s PRIMARY KEY is not supported through ALTER TABLE; it can only be specified during . |
NOT VALID | Create unvalidated constraints. When creating an unvalidated constraint, the system does not check that existing table data satisfies the constraint. The constraint is still enforced when table data is modified. An unvalidated constraint can later be validated using VALIDATE CONSTRAINT. |
Changing primary keys with ADD CONSTRAINT... PRIMARY KEY
When you change a primary key with ALTER TABLE... ALTER PRIMARY KEY, the existing primary key index becomes a secondary index. The secondary index created by ALTER PRIMARY KEY takes up node memory and can slow down write performance to a cluster. If you do not have queries that filter on the primary key that you are replacing, you can use ADD CONSTRAINT to replace the existing primary index without creating a secondary index.
You can use ADD CONSTRAINT... PRIMARY KEY to add a primary key to an existing table if one of the following is true:
- No primary key was explicitly defined at . In this case, the table is created with a default . Using
ADD CONSTRAINT... PRIMARY KEYdrops the default primary key and replaces it with a new primary key. - A statement precedes the
ADD CONSTRAINT... PRIMARY KEYstatement, in the same transaction. For an example, see Drop and add the primary key constraint.
Aliases
In CockroachDB, the following are aliases forALTER TABLE... ADD CONSTRAINT... PRIMARY KEY:
ALTER TABLE... ADD PRIMARY KEY
ALTER COLUMN
Use ALTER TABLE... ALTER COLUMN to do the following:
- Set, change, or drop a column’s .
- Set or drop a column’s .
- Set, change, or drop an .
- Change a column’s .
- Set the visibility of a column.
Support for altering column data types is , with certain limitations. For details, see Altering column data types.
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
column\_name | The name of the column to modify. |
a\_expr | The new to set. |
b\_expr | The to set. |
[NOT] VISIBLE | The visibility of a column when using \* in a . |
typename | The new you want to use. Support for altering column types is , with certain limitations. For details, see Alter column data types. |
USING a\_expr | How to compute a new column value from the old column value. |
Alter column data types
Support for altering column data types is , with certain limitations. To enable column type altering, set theenable_experimental_alter_column_type_general to true.
The following are equivalent in CockroachDB:
ALTER TABLE... ALTER... TYPEALTER TABLE... ALTER COLUMN TYPEALTER TABLE... ALTER COLUMN SET DATA TYPE
Limitations on altering data types
You cannot alter the data type of a column if:- The column is part of an .
- The column has .
- The column owns a .
- The column has a . This will result in an
ERROR:... column... cannot also have a DEFAULT expressionwithSQLSTATE: 42P16. - The
ALTER COLUMN TYPEstatement is part of a combinedALTER TABLEstatement. - The
ALTER COLUMN TYPEstatement is inside an .
Most
ALTER COLUMN TYPE changes are finalized asynchronously. Schema changes on the table with the altered column may be restricted, and writes to the altered column may be rejected until the schema change is finalized.ALTER PRIMARY KEY
Use ALTER TABLE... ALTER PRIMARY KEY to change the of a table.
Note the following:
- You cannot change the primary key of a table that is currently undergoing a primary key change, or any other .
ALTER PRIMARY KEYmight need to rewrite multiple indexes, which can make it an expensive operation.- When you change a primary key with
ALTER PRIMARY KEY, the old primary key index becomes a secondary index. This helps optimize the performance of queries that still filter on the old primary key column. ALTER PRIMARY KEYdoes not alter the on a table or its indexes, even if a partition is defined on . If you alter the primary key of a partitioned table, you must update the table partition accordingly.- The secondary index created by
ALTER PRIMARY KEYwill not be partitioned, even if a partition is defined on . To ensure that the table is partitioned correctly, you must create a partition on the secondary index, or drop the secondary index. - Any new primary key column set by
ALTER PRIMARY KEYmust have an existing . To add aNOT NULLconstraint to an existing column, useALTER TABLE... ALTER COLUMN... SET NOT NULL.
Required privileges
The user must have theCREATE on a table to alter its primary key.
Parameters
| Parameter | Description |
|---|---|
index\_params | The name of the column(s) that you want to use for the primary key. These columns replace the current primary key column(s). |
USING HASH | Creates a . |
CONFIGURE ZONE
ALTER TABLE... CONFIGURE ZONE is used to add, modify, reset, or remove replication zones for a table. To view details about existing replication zones, use . For more information about replication zones, see .
You can use replication zones to control the number and location of replicas for specific sets of data, both when replicas are first added and when they are rebalanced to maintain cluster equilibrium.
For examples, see Replication Controls.
For instructions showing how to troubleshoot replication zones that may be misconfigured, see .
Required privileges
The user must be a member of the or have been granted or privileges. To configure , the user must be a member of theadmin role.
Parameters
| Parameter | Description |
|---|---|
variable | The name of the to change. |
value | The value of the to change. |
DISCARD | Remove a replication zone. |
DROP COLUMN
Use ALTER TABLE... DROP COLUMN to remove columns from a table.
When used in an explicit transaction combined with other schema changes to the same table,
DROP COLUMN can result in data loss if one of the other schema changes fails or is canceled. To work around this, move the DROP COLUMN statement to its own explicit transaction or run it in a single statement outside the existing transaction.DROP COLUMN drops any on the column being dropped, and any indexes that reference the column, including indexes with that reference the column.
For examples, see Drop columns.
Known limitations
- CockroachDB prevents a column from being dropped if it is referenced by a predicate. To drop such a column, the partial indexes need to be dropped first using .
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
column\_name | The name of the column you want to drop. When a column with a constraint is dropped, the CHECK constraint is also dropped. |
CASCADE | Drop the column even if objects (such as ) depend on it; drop the dependent objects, as well. CASCADE will drop a column with a foreign key constraint if it is the only column in the reference. CASCADE does not list the objects it drops, so should be used cautiously. CASCADE is not required to drop an indexed column, or a column that is referenced by an index. By default, DROP COLUMN drops any on the column being dropped, and any indexes that reference the column, including with predicates that reference the column and indexes with that reference the column. |
RESTRICT | (Default) Do not drop the column if any objects (such as ) depend on it. |
DROP CONSTRAINT
Use ALTER TABLE... DROP CONSTRAINT to remove and constraints from columns.
constraints can be dropped with DROP CONSTRAINT if an statement follows the DROP CONSTRAINT statement in the same transaction.
When you change a primary key with , the old primary key index becomes a secondary index. If you do not want the old primary key to become a secondary index, use DROP CONSTRAINT/ to change the primary key.
For information about removing other constraints, see .
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
constraint\_name | The name of the constraint you want to drop. |
EXPERIMENTAL_AUDIT
ALTER TABLE... EXPERIMENTAL_AUDIT enables or disables the recording of SQL audit events to the logging channel for a table. The SENSITIVE_ACCESS log output is also called the SQL audit log. For details on using SQL audit logs, see .
This feature is in and subject to change. To share feedback and/or issues, contact Support.
- Full text of the query (which may include personally identifiable information (PII))
- Date/Time
- Client address
- Application name
Required privileges
Only members of theadmin role can enable audit logs on a table. By default, the root user belongs to the admin role.
Parameters
| Parameter | Description |
|---|---|
READ | Log all table reads to the audit log file. |
WRITE | Log all table writes to the audit log file. |
OFF | Turn off audit logging. |
This command logs all reads and writes, and both the
READ and WRITE parameters are required (as shown in the examples).OWNER TO
ALTER TABLE... OWNER TO is used to change the owner of a table.
For examples, see Change table owner.
Required privileges
To change the owner of a table, the user must be anadmin user, or the current owner of the table and a member of the new owner . The new owner role must also have the CREATE on the schema to which the table belongs.
Parameters
| Parameter | Description |
|---|---|
role\_spec | The role to set as the owner of the table. |
PARTITION BY
Required privileges
ALTER TABLE... PARTITION BY is used to partition, re-partition, or un-partition a table. After defining partitions, CONFIGURE ZONE is used to control the replication and placement of partitions.
For examples, see Define partitions.
Parameters
| Parameter | Description |
|---|---|
name\_list | List of columns you want to define partitions on (in the order they are defined in the primary key). |
list\_partitions | Name of list partition followed by the list of values to be included in the partition. |
range\_partitions | Name of range partition followed by the range of values to be included in the partition. |
RENAME COLUMN
ALTER TABLE... RENAME COLUMN changes the name of a column in a table.
It is not possible to rename a column referenced by a view. For more details, see .
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
IF EXISTS | Rename the column only if a table of table\_name exists; if one does not exist, do not return an error. |
column\_name | The current name of the column. |
column\_new\_name | The you want to use for the column, which must be unique to its table and follow these . |
RENAME CONSTRAINT
ALTER TABLE... RENAME CONSTRAINT changes the name of a constraint on a column.
It is not possible to rename a constraint for a column referenced by a view. For more details, see .
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
IF EXISTS | Rename the constraint only if a constraint of current\_name exists; if one does not exist, do not return an error. |
constraint\_name | The current name of the constraint. |
constraint\_new\_name | The new you want to use for the constraint, which must be unique to its table and follow these . |
RENAME TO
ALTER TABLE... RENAME TO changes the name of a table.
ALTER TABLE... RENAME TO cannot be used to move a table from one schema to another. To change a table’s schema, use SET SCHEMA.
ALTER TABLE... RENAME TO cannot be used to move a table from one database to another. To change a table’s database, use and .
It is not possible to rename a table referenced by a view. For more details, see .
Required privileges
The user must have theDROP on the table and the CREATE on the parent database.
Parameters
| Parameter | Description |
|---|---|
table\_new\_name | The new name of the table, which must be unique within its database and follow these . When the parent database is not set as the default, the name must be formatted as database.name. The and statements use a temporary table called excluded to handle uniqueness conflicts during execution. It’s therefore not recommended to use the name excluded for any of your tables. |
RESET {storage parameter}
ALTER TABLE... RESET {storage parameter} reverts the value of a storage parameter on a table to its default value.
To reset a storage parameter on an existing index, you must drop and .
Required privileges
The user must be a member of the or roles, or have the on the table.Parameters
| Parameter | Description |
|---|---|
storage\_parameter\_key | The name of the storage parameter you are changing. See Table storage parameters for a list of available parameters. |
SET {storage parameter}
ALTER TABLE... SET {storage parameter} sets a storage parameter on an existing table.
To set a storage parameter on an existing index, you must drop and .
Required privileges
The user must be a member of the or roles, or have the on the table.Parameters
| Parameter | Description |
|---|---|
storage\_parameter\_key | The name of the storage parameter. See Table storage parameters for a list of available parameters. |
value | The value to assign the storage parameter. |
Table storage parameters
| Parameter name | Description | Data type | Default value |
|---|---|---|---|
exclude\_data\_from\_backup | Exclude the data in this table from any future backups. | Boolean | false |
New in v23.2.1:schema\_locked | Disallow on this table. Enabling schema\_locked can help running on this table. | Boolean | false |
sql\_stats\_automatic\_collection\_enabled | Enable automatic collection of for this table. | Boolean | true |
sql\_stats\_automatic\_collection\_min\_stale\_rows | Minimum number of stale rows in this table that will trigger a statistics refresh. | Integer | 500 |
sql\_stats\_automatic\_collection\_fraction\_stale\_rows | Fraction of stale rows in this table that will trigger a statistics refresh. | Float | 0.2 |
sql\_stats\_forecasts\_enabled | Enable collection for this table. | Boolean | true |
autovacuum_enabledfillfactor
SET LOCALITY
ALTER TABLE.. SET LOCALITY changes the of a in a .
While CockroachDB is processing an ALTER TABLE.. SET LOCALITY statement that enables or disables REGIONAL BY ROW on a table within a database, any and statements on that database will fail.
For examples, see Set localities.
Required privileges
The user must be a member of the or roles, or have the on the table.Parameters
| Parameter | Description |
|---|---|
locality | The LOCALITY clause, followed by the to apply to this table. Allowed values:
|
SET SCHEMA
ALTER TABLE... SET SCHEMA changes the of a table.
CockroachDB supports
SET SCHEMA as an .Required privileges
The user must have theDROP on the table, and the CREATE privilege on the schema.
Parameters
| Parameter | Description |
|---|---|
schema\_name | The name of the new schema for the table. |
SCATTER
ALTER TABLE... SCATTER runs a specified set of ranges for a table or index through the queue. If many ranges have been created recently, the replication queue may transfer some leases to other replicas to balance load across the cluster.
Note that this statement makes a best-effort attempt to redistribute replicas and leaseholders for the ranges of an index. It does not return an error even if replicas are not moved.
SCATTER has the potential to result in data movement proportional to the size of the table or index being scattered, thus taking additional time and resources to complete.Required privileges
The user must have theINSERT on the table or index.
Parameters
| Parameter | Description |
|---|---|
table\_name | The name of the table that you want to scatter. |
table\_index\_name | The name of the index that you want to scatter. |
expr\_list | A list of in the form of the primary key of the table or the specified index. |
SPLIT AT
ALTER TABLE... SPLIT AT forces a at a specified row in the table.
CockroachDB breaks data into ranges. By default, CockroachDB attempts to keep ranges below . To do this, the system will automatically if it grows larger than this limit. For most use cases, this automatic range splitting is sufficient, and you should never need to worry about when or where the system decides to split ranges.
However, there are reasons why you may want to perform manual splits on the ranges that store tables or indexes:
- When a table only consists of a single range, all writes and reads to the table will be served by that range’s . If a table only holds a small amount of data but is serving a large amount of traffic, load distribution can become unbalanced and a can occur. Splitting the table’s ranges manually can allow the load on the table to be more evenly distributed across multiple nodes. For tables consisting of more than a few ranges, load will naturally be distributed across multiple nodes and this will not be a concern.
- When a table is created, it will only consist of a single range. If you know that a new table will immediately receive significant write traffic, you may want to preemptively split the table based on the expected distribution of writes before applying the load. This can help avoid reduced workload performance that results when automatic splits are unable to keep up with write traffic and a occurs.
Required privileges
The user must have theINSERT on the table.
Parameters
| Parameter | Description |
|---|---|
select\_stmt | A that produces one or more rows at which to split the table. |
a\_expr | The expiration of the split enforcement on the table. This can be a , , , or . |
UNSPLIT AT
ALTER TABLE... UNSPLIT AT removes a split enforcement on a , at a specified row in the table.
Removing a split enforcement from a table or index (“unsplitting”) allows CockroachDB to merge ranges as needed, to help improve your cluster’s performance. For more information, see .
For examples, see Split and unsplit tables.
Required privileges
The user must have theINSERT on the table.
Parameters
| Parameter | Description |
|---|---|
select\_stmt | A that produces one or more rows at which to unsplit a table. |
ALL | Remove all split enforcements for a table. |
VALIDATE CONSTRAINT
ALTER TABLE... VALIDATE CONSTRAINT checks whether values in a column match a on the column.
This statement is especially useful after applying a constraint to an existing column via ADD CONSTRAINT. In this case, VALIDATE CONSTRAINT can be used to find values already in the column that do not match the constraint.
For examples, see Validate constraints.
Required privileges
The user must have theCREATE on the table.
Parameters
| Parameter | Description |
|---|---|
constraint\_name | The name of the constraint to validate. |
View schema changes
This schema change statement is registered as a job. You can view long-running jobs with .Examples
Add columns
The following examples use the . To follow along, run to start a temporary, in-memory cluster with thebank schema and dataset preloaded:
Add a single column
Add multiple columns
Add a column with a NOT NULL constraint and a DEFAULT value
Add a column with a UNIQUE constraint
Add a column with a FOREIGN KEY constraint
Add a column with collation
Add a column and assign it to a column family
Add a column and assign it to a new column family
Add a column and assign it to an existing column family
Add a column and create a new column family if column family does not exist
Move a column from one column family to another
Moving frequently updated columns to their own . To move a column from one column family to another column family, create a temporary, in the target column family, then rename the columns. Once this succeeds, you can drop the original, now renamed column. For example, to move thenew_name column from f2 to f1:
-
Create a temporary computed column in the target column family of the same data type as the column you want to move:
This causes
newer_nameto have the same values asnew_name. -
Rename the columns:
-
Drop the old column:
You must set the to
false to drop a column in a table that has data.Add a column with an ON UPDATE expression
ON UPDATE expressions set the value for a column when other values in a row are updated.
For example, suppose you add a new column to the bank table:
bank table is updated, CockroachDB re-evaluates the ON UPDATE expression and updates the last_updated column with the result.
Add constraints
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Add the UNIQUE constraint
Adding the requires that all of a column’s values be distinct from one another (except for NULL values).
Add the CHECK constraint
Adding the requires that all of a column’s values evaluate to TRUE for a Boolean expression.
ADD CONSTRAINT statement will fail.
Add constraints to columns created during a transaction
You can add check constraints to columns that were created earlier in the transaction. For example:The entire transaction will be rolled back, including any new columns that were added, in the following cases:
- If an existing column is found containing values that violate the new constraint.
- If a new column has a default value or is a that would have contained values that violate the new constraint.
Add the foreign key constraint with CASCADE
To add a foreign key constraint, use the following steps.
Given two tables, users and vehicles, without foreign key constraints:
ON DELETE CASCADE will ensure that when the referenced row is deleted, all dependent objects are also deleted.
CASCADE does not list the objects it drops or updates, so it should be used with caution.By default, referenced columns must be in the same database as the referencing foreign key column. To enable cross-database foreign key references, set the
sql.cross_db_fks.enabled to true.Drop and add a primary key constraint
Suppose that you want to addcreation_time to the composite primary key of the promo_codes table, without creating a secondary index of the existing primary key. To do so, use DROP CONSTRAINT and ADD CONSTRAINT in a single ALTER TABLE statement.
-
View the details of the
promo_codestable: -
Add a constraint to the
creation_timecolumn withALTER COLUMN: -
To issue the schema change atomically, use single statements as an implicit transaction.
DROP CONSTRAINTandADD CONSTRAINTcan be combined in a singleALTER TABLEstatement:
You should not execute the schema change with multiple statements within an explicit transaction. Refer to .
-
View the updated table structure:
UNIQUE secondary index called promo_codes_code_key. Instead, there is just one index for the primary key constraint.
Add a unique index to a REGIONAL BY ROW table
In , most users should use instead of explicit index . When you add an index to a REGIONAL BY ROW table, it is automatically partitioned on the . Explicit index partitioning is not required.
While CockroachDB process an or statement on a particular database, creating or modifying an index will throw an error. Similarly, all and statements will be blocked while an index is being modified on a REGIONAL BY ROW table within the same database.
This example assumes you have a simulated multi-region database running on your local machine following the steps described in . It shows how a UNIQUE index is partitioned, but it’s similar to how all indexes are partitioned on REGIONAL BY ROW tables.
To show how the automatic partitioning of indexes on REGIONAL BY ROW tables works, we will:
- to the
userstable in the . - Add a to that column.
- Verify that the index is automatically partitioned for better multi-region performance by using and .
email since that is something that should be unique per user.
user_email_unique index is now partitioned by the database regions europe-west1, us-east1, and us-west1.
email column of an existing row is updated, the database needs to do the following additional work when indexes are partitioned:
- Run a one-time-only validation query to ensure that the existing data in the table satisfies the unique constraint.
- Thereafter, the will automatically add a “uniqueness check” when necessary to any , , or statement affecting the columns in the unique constraint.
Using DEFAULT gen_random_uuid() in REGIONAL BY ROW tables
To auto-generate unique row identifiers in REGIONAL BY ROW tables, use the column with the gen_random_uuid() as the :
When using
DEFAULT gen_random_uuid() on columns in REGIONAL BY ROW tables, uniqueness checks on those columns are disabled by default for performance purposes. CockroachDB assumes uniqueness based on the way this column generates . To enable this check, you can modify the sql.optimizer.uniqueness_checks_for_gen_random_uuid.enabled . Note that while there is virtually no chance of a collision occurring when enabling this setting, it is not truly zero.Using implicit vs. explicit index partitioning in REGIONAL BY ROW tables
In REGIONAL BY ROW tables, all indexes are partitioned on the region column (usually called ).
These indexes can either include or exclude the partitioning key (crdb_region) as the first column in the index definition:
- If
crdb_regionis included in the index definition, a will enforce uniqueness on the set of columns, just like it would in a non-partitioned table. - If
crdb_regionis excluded from the index definition, that serves as a signal that CockroachDB should enforce uniqueness on only the columns in the index definition.
REGIONAL BY ROW table that has an implicitly partitioned UNIQUE index, the must add uniqueness checks.
Whether or not to explicitly include crdb_region in the index definition depends on the context:
- If you only need to enforce uniqueness at the region level, then including
crdb_regionin theUNIQUEindex definition will enforce these semantics and allow you to get better performance on s, s, and s, since there will not be any added latency from uniqueness checks. - If you need to enforce global uniqueness, you should not include
crdb_regionin theUNIQUE(or ) index definition, and the database will automatically ensure that the constraint is enforced.
- Create a schema that includes an explicitly partitioned index, and an implicitly partitioned index.
- Check the output of several queries using
EXPLAINto show the differences in behavior between the two.
-
Start as follows:
-
Create a multi-region database and an
employeestable. There are three indexes in the table, allUNIQUEand all partitioned by thecrdb_regioncolumn. The table schema guarantees that bothidandemailare globally unique, whiledesk_idis only unique per region. The indexes onidandemailare implicitly partitioned, while the index on(crdb_region, desk_id)is explicitly partitioned.UNIQUEindexes can only directly enforce uniqueness on all columns in the index, including partitioning columns, so each of these indexes enforce uniqueness forid,email, anddesk_idper region, respectively. -
In the following statement, we add a new user with the required
id,email, anddesk_idcolumns. CockroachDB needs to do additional work to enforce global uniqueness for theidandemailcolumns, which are implicitly partitioned. This additional work is in the form of “uniqueness checks” that the optimizer adds as part of mutation queries.The followingEXPLAINoutput shows that the optimizer has added twoconstraint-checkpost queries to check the uniqueness of the implicitly partitioned indexesidandemail. There is no check needed fordesk_id(really(crdb_region, desk_id)), since that constraint is automatically enforced by the explicitly partitioned index we added in the preceding statement. -
The following statement updates the user’s
emailcolumn. Because the unique index on theemailcolumn is implicitly partitioned, the optimizer must perform a uniqueness check.In the followingEXPLAINoutput, the optimizer performs a uniqueness check foremailsince we’re not updating any other columns (see theconstraint-checksection). -
If we only update the user’s
desk_id, no uniqueness checks are needed, since the index on that column is explicitly partitioned (it’s really(crdb_region, desk_id)).Because no uniqueness check is needed, there is noconstraint-checksection in theEXPLAINoutput.
Alter columns
Set or change a DEFAULT value
Setting the inserts the value when data’s written to the table without explicitly defining the value for the column. If the column already has a DEFAULT value set, you can use this statement to change it.
The following example inserts the Boolean value true whenever you inserted data to the subscriptions table without defining a value for the newsletter column.
Remove DEFAULT constraint
If the column has a defined , you can remove the constraint, which means the column will no longer insert a value by default if one is not explicitly defined for the column.
Set NOT NULL constraint
To specify that the column cannot contain NULL values, set the .
Remove NOT NULL constraint
If the column has the applied to it, you can remove the constraint, which means the column becomes optional and can have NULL values written into it.
Convert a computed column into a regular column
You can convert a stored, computed column into a regular column by usingALTER TABLE.
In this example, create a simple table with a computed column:
full_name column is computed from the first_name and last_name columns without the need to define a . You can view the column details with the statement:
full_name) to a regular column:
Alter the formula for a computed column
To alter the formula for a computed column, you must and the column back with the new definition. Take the following table for instance:d:
Convert to a different data type
The database has acustomer table with a column c_credit_lim of type DECIMAL(10,2):
DECIMAL to STRING:
-
Set the
enable_experimental_alter_column_type_generaltotrue: -
Alter the column type:
-
Verify the type:
Change a column type’s precision
Thecustomer table contains a column c_balance of type DECIMAL(12,2):
c_balance column from DECIMAL(12,2) to DECIMAL(14,2):
Change a column’s type using an expression
You can change the data type of a column and create a new, computed value from the old column values, with aUSING clause. For example:
Set the visibility of a column
To specify that a column won’t be returned when using* in a , set the NOT VISIBLE property. You can set the NOT VISIBLE property only on individual columns.
For example, the users table of the contains the credit_card column. If you don’t want users to see that column when running SELECT * FROM users;, you can hide it as follows:
SELECT *, the column does not appear:
target_elem parameter:
Alter a primary key
Alter a single-column primary key
Suppose that you are storing the data for users of your application in a table calledusers, defined by the following CREATE TABLE statement:
name column. This is a poor choice, as some users likely have the same name, and all primary keys enforce a UNIQUE constraint on row values of the primary key column. Per our , you should instead use a UUID for single-column primary keys, and populate the rows of the table with generated, unique values.
You can add a column and change the primary key with a couple of ALTER TABLE statements:
Alter an existing primary key to use hash sharding
Let’s assume theevents table already exists:
USING HASH clause at the end of the key definition:
users_name_key. If you do not want the old primary key to become a secondary index when changing a primary key, you can use / instead.
Configure replication zones
Setup
The following examples use MovR, a fictional vehicle-sharing application, to demonstrate CockroachDB SQL statements. For more information about the MovR example application and dataset, see . To follow along, run with the--geo-partitioned-replicas flag. This command opens an interactive SQL shell to a temporary, 9-node in-memory cluster with the movr database.
Create a replication zone for a table
To control replication for a specific table, use theALTER TABLE... CONFIGURE ZONE statement to define the relevant values (other values will be inherited from the parent zone):
Edit a replication zone
Reset a replication zone
Remove a replication zone
When you discard a zone configuration, the objects it was applied to will then inherit a configuration from an object “the next level up”; e.g., if the object whose configuration is being discarded is a table, it will use its parent database’s configuration.You cannot
DISCARD any zone configurations on multi-region tables, indexes, or partitions if the created the zone configuration.Drop columns
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Drop a column
If you no longer want a column in a table, you can drop it.sql_safe_updates must be set to false.
Prevent dropping columns with dependent objects (RESTRICT)
If the column has dependent objects, such as , CockroachDB will not drop the column by default. However, if you want to be sure of the behavior you can include the RESTRICT clause.
Drop a column and its dependent objects (CASCADE)
If you want to drop the column and all of its dependent options, include the CASCADE clause.
CASCADE does not list objects it drops, so should be used cautiously.Drop an indexed column
DROP COLUMN drops a column and any indexes on the column being dropped.
Drop constraints
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Drop a foreign key constraint
Configure audit logging
Turn on audit logging
Let’s say you have acustomers table that contains personally identifiable information (PII). To turn on audit logs for that table, run the following command:
SENSITIVE_ACCESS channel in a event that looks like the following:
The preceding example shows the default log format. This can be changed to a different format (e.g., JSON). For details, see .
ALTER statement for each table.
Turn off audit logging
To turn off logging, issue the following command:Change table owner
Change a table’s owner
Suppose that the current owner of therides table is root and you want to change the owner to a new user named max.
max, query the pg_catalog.pg_tables table:
If the user running the command is not an admin user, they must own the table and be a member of the new owning role. Also, the new owner role must also have the
CREATE on the schema to which the table belongs.Define partitions
Define a list partition on a table
Suppose we have a table calledstudents_by_list, and the primary key of the table is defined as (country, id). We can define partitions on the table by list:
Define a range partition on a table
Suppose we have a table calledstudents_by_range, and the primary key of the table is defined as (expected_graduation_date, id). We can define partitions on the table by range:
Define subpartitions on a table
Suppose we have a table namedstudents, and the primary key is defined as (country, expected_graduation_date, id). We can define partitions and subpartitions on the table:
Repartition a table
Unpartition a table
Rename columns
Rename a column
Add and rename columns atomically
Some subcommands can be used in combination in a single statement. For example, let’s say you create ausers table with 2 columns, an id column for the primary key and a name column for each user’s last name:
ALTER TABLE statement renaming name to last_name, adding first_name, and adding a called name that concatenates first_name and last_name:
Rename constraints
Rename a constraint
Rename tables
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Rename a table
IF EXISTS:
Set and reset storage parameters
Exclude a table’s data from backups
In some situations, you may want to exclude a table’s row data from a . For example, you have a table that contains high-churn data that you would like to more quickly than the schedule for the database or cluster holding the table. You can use theexclude_data_from_backup = true parameter with a or ALTER TABLE statement to mark a table’s row data for exclusion from a backup.
For more detail and an example through the backup and process using this parameter, see .
To set the exclude_data_from_backup parameter for a table, run the following:
CREATE statement for this table will now show the parameter set:
user_promo_codes table. The table will still be present in the backup, but it will be empty.
To remove this parameter from a table, run:
Reset a storage parameter
The followingttl_test table has three TTL-related storage parameters active on the table:
Set localities
on
REGIONAL BY TABLE, REGIONAL BY ROW, and GLOBAL tables is supported with some limitations — see for more detail.Set the table locality to REGIONAL BY TABLE
To optimize read and write access to the data in a table from the primary region, use the following statement, which sets the table’s home region to the primary region:
us-east-1 region, use the following statement, which sets the table’s home region to us-east-1:
If no region is supplied,
REGIONAL BY TABLE defaults the table’s home region to the primary region.Set the table locality to REGIONAL BY ROW
Before setting the locality to
REGIONAL BY ROW on a table targeted by a changefeed, read the considerations in .crdb_internal_region that represents the row’s . By default, this column is called crdb_region and is hidden. To see a row’s home region, issue a statement like the following:
- Let CockroachDB set the row’s home region automatically. It will use the region of the from which the row is inserted.
-
Set the home region explicitly using an statement like the following:
gateway_region(). If the value returned by gateway_region() does not belong to the multi-region database the table is a part of, the home region defaults to the database’s primary region.
For more information about how this table locality works, see .
Note that you can use a name other than crdb_region for the hidden column by using the following statements:
REGIONAL BY ROW AS column, as long as the column is of type crdb_internal_region and is not nullable. For example, you could modify the to have a region column generated as:
Turn on auto-rehoming for REGIONAL BY ROW tables
This feature is in and subject to change. To share feedback and/or issues, contact Support.
REGIONAL BY ROW tables are automatically set to the gateway region of any or statements that write to those rows. This functionality is provided by adding an to the crdb_region column of newly created regional by row tables.
To enable auto-rehoming using the , issue the following statement:
- It will only apply to newly created
REGIONAL BY ROWtables, using anON UPDATEexpression that is added to thecrdb_regioncolumn. ExistingREGIONAL BY ROWtables will not be auto-rehomed. - The
crdb_regioncolumn from aREGIONAL BY ROWtable cannot be referenced as a from another table.
REGIONAL BY ROW table, manually update it using an ALTER TABLE... ALTER COLUMN statement with an ON UPDATE expression:
Example
- Follow steps 1 and 2 from the tutorial. This will involve starting a cluster in a terminal window (call it terminal 1).
-
From the running in terminal 1, set the setting that enables auto-rehoming. You must issue this setting before creating the
REGIONAL BY ROWtables that you want auto-rehomed. - In a second terminal window (call it terminal 2), onward to finish loading the cluster with data and applying the multi-region SQL configuration.
-
Switch back to terminal 1, and check the gateway region of the node you are currently connected to:
-
Open another terminal (call it terminal 3), and use to connect to a node in a different region in the demo cluster:
-
From the SQL shell prompt that appears in terminal 3, switch to the
movrdatabase, and verify that the current gateway node is in a different region (us-west1): -
Still in terminal 3, update a row in the
vehiclestable that is homed in theus-east1region. After the update, it should be homed in the current gateway node’s home region,us-west1.-
First, pick a row at random from the
us-east1region: -
Next, update that row’s
cityandcurrent_locationto addresses in Seattle, WA (USA). Note that this UUID is different than what you will see in your cluster, so you’ll have to update the query accordingly. -
Finally, verify that the row has been auto-rehomed in this gateway’s region by running the following statement and checking that the
regioncolumn is nowus-west1:
-
First, pick a row at random from the
Set the table locality to GLOBAL
To optimize read access to the data in a table from any region (that is, globally), use the following statement:
Set table schema
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Change the schema of a table
Suppose you want to add thepromo_codes table to a new schema called cockroach_labs.
By default, created in the database belong to the public schema:
Scatter tables
Before scattering, you can view the current replica and leaseholder distribution for a table:Split and unsplit tables
Setup
The following examples use MovR, a fictional vehicle-sharing application, to demonstrate CockroachDB SQL statements. For more information about the MovR example application and dataset, see . To follow along, run with the--geo-partitioned-replicas flag. This command opens an interactive SQL shell to a temporary, 9-node in-memory cluster with the movr database.
Split a table
Split a table with a compound primary key
You may want to split a table with a compound primary key. Suppose that you want MovR to offer ride-sharing services, in addition to vehicle-sharing services. Some users need to sign up to be drivers, so you need adrivers table to store driver information.
city and dl columns. Note that the table automatically generates an id and a dl value if they are not provided.
Because this table has several columns in common with the users table, you can populate the table with values from the users table with an INSERT statement:
Set the expiration on a split enforcement
You can specify the time at which a split enforcement expires by adding aWITH EXPIRATION clause to your SPLIT statement. Supported expiration values include , , , and .
split_enforced_until column. The table also contains information about ranges in your CockroachDB cluster, including the split_enforced_until column.
Unsplit a table
Create adrivers table and split the table based on the compound primary key as described in Split a table with a compound primary key.
To remove the split enforcements, run the following:
split_enforced_until column. The table also contains information about ranges in your CockroachDB cluster, including the split_enforced_until column.
drivers table is still split into ranges at specific primary key column values, but the split_enforced_until column is now NULL for all ranges in the table. The split is no longer enforced, and CockroachDB can in the table as needed.
Validate constraints
Setup
To follow along, run to start a temporary, in-memory cluster with the sample dataset preloaded:Validate a constraint
In the example Add the foreign key constraint withCASCADE, we add a foreign key constraint as follows:
vehicles table prior to the creation of the users_fk constraint conforms to that constraint, run the following:
If present in a statement, the table is considered validated because an empty table trivially meets its constraints.

