> ## Documentation Index
> Fetch the complete documentation index at: https://www.cockroachlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a User-defined Schema

export const InternalLink = ({version, path = "", children, ...props}) => {
  let detectedVersion = version || "stable";
  if (typeof window !== 'undefined' && !version) {
    const match = window.location.pathname.match(/\/docs\/([^/]+)/);
    if (match) {
      detectedVersion = match[1];
    }
  }
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
  return <a href={`/docs/${detectedVersion}/${normalizedPath}`} {...props}>
      {children}
    </a>;
};

This page provides best-practice guidance on creating user-defined schemas, with some simple examples based on Cockroach Labs's fictional vehicle-sharing company, <InternalLink path="movr">MovR</InternalLink>.

<Tip>
  For detailed reference documentation on the `CREATE SCHEMA` statement, including additional examples, see the <InternalLink path="create-schema">`CREATE SCHEMA` syntax page</InternalLink>.
</Tip>

## Before you begin

Before reading this page, do the following:

* <InternalLink version="cockroachcloud" path="quickstart">Create a CockroachDB Standard cluster</InternalLink> or <InternalLink path="start-a-local-cluster">start a local cluster</InternalLink>.
* <InternalLink path="schema-design-overview">Review the database schema objects</InternalLink>.
* <InternalLink path="schema-design-database">Create a database</InternalLink>.

## Create a user-defined schema

User-defined schemas belong to the second level of the <InternalLink path="sql-name-resolution#naming-hierarchy">CockroachDB naming hierarchy</InternalLink>.

To create a user-defined schema, use a <InternalLink path="create-schema">`CREATE SCHEMA` statement</InternalLink>, following [the user-defined schema best practices](#user-defined-schema-best-practices). After reviewing the best practices, see the example we provide [below](#examples).

### User-defined schema best practices

Here are some best practices to follow when creating and using user-defined schemas:

* If you want to create multiple objects (e.g., tables or views) with the same name in your cluster, do so in different user-defined schemas in the same database.
* If you want to separate lower-level objects (e.g., a set of <InternalLink path="schema-design-table">tables</InternalLink> or <InternalLink path="views">views</InternalLink>) for access or organizational purposes, do not create those objects in the preloaded <InternalLink path="sql-name-resolution#naming-hierarchy">`public` schema</InternalLink>. Instead, create user-defined schemas, and then create the objects in the user-defined schemas.
* Create user-defined schemas as a member of <InternalLink path="security-reference/authorization#admin-role">the `admin` role</InternalLink> (e.g., as the <InternalLink path="security-reference/authorization">`root` user</InternalLink>), and then give ownership of them to a <InternalLink path="schema-design-overview#control-access-to-objects">different user</InternalLink>, with fewer privileges across the database, following <InternalLink path="security-reference/authorization#authorization-best-practices">authorization best practices</InternalLink>.
* When you create a user-defined schema, take note of the <InternalLink path="security-reference/authorization#object-ownership">object's owner</InternalLink>. You can specify the owner in a `CREATE SCHEMA` statement with the <InternalLink path="create-schema#parameters">`AUTHORIZATION` keyword</InternalLink>. If `AUTHORIZATION` is not specified, the owner will be the user creating the user-defined schema.
* Do not create user-defined schemas in the preloaded `defaultdb` database. Instead, use a database <InternalLink path="schema-design-database">you have created</InternalLink>. If you do not specify a database in the `CREATE SCHEMA` statement, the user-defined schema will be created in your SQL session's <InternalLink path="sql-name-resolution#current-database">current database</InternalLink>.
* When referring to a lower-level object in a database (e.g., a table), include the object's schema name (e.g., `schema_name.table_name`). Specifying the schema name in a lower-level object reference can prevent users from attempting to access the wrong object, if there are multiple objects with the same name in a database.
* Use a <InternalLink path="third-party-database-tools#schema-migration-tools">database schema migration tool</InternalLink> or the <InternalLink path="cockroach-sql">CockroachDB SQL client</InternalLink> instead of a <InternalLink path="third-party-database-tools#drivers">client library</InternalLink> to execute <InternalLink path="online-schema-changes">database schema changes</InternalLink>.

### Examples

Suppose you want to separate the tables and indexes in your cluster such that one user manages a group of tables, and another user manages a different group of tables. You can do this with two different user-defined schemas, owned by two different SQL users, with fewer privileges than the `root` user.

Open the `dbinit.sql` file that you created in the <InternalLink path="schema-design-database">Create a Database</InternalLink> example, and add the following statements under the `CREATE DATABASE` statement:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
USE movr;

CREATE USER IF NOT EXISTS max;
GRANT CREATE ON DATABASE movr TO max;

CREATE USER IF NOT EXISTS abbey;
GRANT CREATE ON DATABASE movr TO abbey;
```

The first statement sets the `movr` database as the <InternalLink path="sql-name-resolution#current-database">current database</InternalLink>. The next two sets of statements create SQL users named `max` and `abbey` in the `movr` database, with <InternalLink path="security-reference/authorization#supported-privileges">`CREATE` privileges on the database</InternalLink>. `CREATE` privileges will allow each user to create tables in the database.

Now, under the `CREATE USER` statements, add `DROP SCHEMA` and `CREATE SCHEMA` statements for each user's user-defined schema:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
DROP SCHEMA IF EXISTS max_schema CASCADE;
CREATE SCHEMA max_schema AUTHORIZATION max;

DROP SCHEMA IF EXISTS abbey_schema CASCADE;
CREATE SCHEMA abbey_schema AUTHORIZATION abbey;
```

The first set of statement clears the database of any existing schema named `max_schema`, and then creates a schema named `max_schema` with the owner `max`. The next set of statements does the same, but for `abbey_schema`, with `abbey` as the owner.

It might also be a good idea to <InternalLink path="grant#supported-privileges">grant the `USAGE` privilege</InternalLink> on each schema to the other user in the database. This will allow the other user to access objects in the schema, but it will not let them delete the schema, or create objects inside of it.

Under the `CREATE SCHEMA` statements for each user-defined schema, add a `GRANT` statement granting `USAGE` privileges on the schema to the other user.

The `dbinit.sql` file should now look something link this:

```sql theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
CREATE DATABASE IF NOT EXISTS movr;

USE movr;

CREATE USER IF NOT EXISTS max;
GRANT CREATE ON DATABASE movr TO max;

CREATE USER IF NOT EXISTS abbey;
GRANT CREATE ON DATABASE movr TO abbey;

DROP SCHEMA IF EXISTS max_schema CASCADE;
CREATE SCHEMA max_schema AUTHORIZATION max;
GRANT USAGE ON SCHEMA max_schema TO abbey;

DROP SCHEMA IF EXISTS abbey_schema CASCADE;
CREATE SCHEMA abbey_schema AUTHORIZATION abbey;
GRANT USAGE ON SCHEMA abbey_schema TO max;
```

To execute the statements in the `dbinit.sql` file as the `root` user, run the following command:

```shell theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
$ cockroach sql \
--certs-dir={certs-directory} \
--user=root \
-f dbinit.sql
```

Before the new users can connect to the cluster and start creating objects, they each need a <InternalLink path="authentication#client-authentication">user certificate</InternalLink>. To create a user certificate for `max`, open a new terminal, and run the following <InternalLink path="cockroach-cert">`cockroach cert`</InternalLink> command:

```shell theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
$ cockroach cert create-client max --certs-dir={certs-directory} --ca-key={my-safe-directory}/ca.key
```

Create a user certificate for `abbey` as well:

```shell theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
$ cockroach cert create-client abbey --certs-dir={certs-directory} --ca-key={my-safe-directory}/ca.key
```

As one of the new users, use a <InternalLink path="show-schemas">`SHOW SCHEMAS` statement</InternalLink> to show the preloaded and user-defined schemas in the `movr` database:

```shell theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
$ cockroach sql \
--certs-dir={certs-directory} \
--user=abbey \
--database=movr \
--execute="SHOW SCHEMAS;"
```

```text theme={"theme":{"light":"catppuccin-mocha","dark":"catppuccin-mocha"}}
     schema_name     | owner
---------------------+--------
  abbey_schema       | abbey
  crdb_internal      | NULL
  information_schema | NULL
  max_schema         | max
  pg_catalog         | NULL
  pg_extension       | NULL
  public             | admin
(7 rows)
```

You're now ready to start adding tables to the `max_schema` user-defined schema as the `max` user, and to the `abbey_schema` user-defined schema as the `abbey` user.

To use a user-defined schema when connecting to your cluster using a connection URL, use the <InternalLink path="connection-parameters#supported-options-parameters">`options` parameter</InternalLink> and set the `search_path` session variable to the schema name. Refer to the <InternalLink path="connection-parameters#example-uri-for-connecting-to-a-database-with-a-user-defined-schema">example</InternalLink>.

For guidance on creating tables, see at <InternalLink path="schema-design-table">Create a Table</InternalLink>.

## What's next?

* <InternalLink path="schema-design-table">Create a Table</InternalLink>
* <InternalLink path="schema-design-indexes">Secondary Indexes</InternalLink>

You might also be interested in the following pages:

* <InternalLink path="create-schema">`CREATE SCHEMA`</InternalLink>
* <InternalLink path="cockroach-commands">`cockroach` Commands Overview</InternalLink>
* <InternalLink path="schema-design-database">Create a Database</InternalLink>
* <InternalLink path="schema-design-overview">Schema Design Overview</InternalLink>
* <InternalLink path="sql-name-resolution#naming-hierarchy">CockroachDB naming hierarchy</InternalLink>
