# [ 살펴보기 ] DrizzleORM - Schema

이전 포스트에서 살펴보았듯이 기존에 생성된 table에 대한 drizzle schema정의해서 사용할 수도 있지만 처음부터 drizzle schema를 통해 table을 생성할 수도 있다. 우선 schema를 정의할 때 사용할 수 있는 대표적인 data type을 살펴보자. ( 해당 포스트는 PostgreSQL을 기준으로 drizzle schema를 살펴본다 )

* integer : PostgreSQL integer type에 해당된다.
    
    ```javascript
    import { integer, pgTable } from "drizzle-orm/pg-core";
    
    // drizzle schema
    export const tableA = pgTable('table_a', {
    	int: integer()
    });
    
    // drizzle schema
    export const tableB = pgTable('table_b', {
    	int1: integer().default(10)
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"int" integer
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"int1" integer DEFAULT 10
    );
    ```
    
* serial : PostgreSQL serial type에 해당된다.
    
    ```javascript
    import { serial, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      serial: serial(),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
      "serial" serial NOT NULL,
    );
    ```
    
* text : PostgreSQL text type에 해당된다.
    
    ```javascript
    import { text, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      text: text()
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"text" text,
    );
    ```
    
* varchar: PostgreSQL character varying(n) type에 해당된다.
    
    ```javascript
    import { varchar, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      varchar1: varchar(),
    });
    
    export const tableB = pgTable('table_b', {
      varchar2: varchar({ length: 256 }),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"varchar1" varchar,
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"varchar2" varchar(256),
    );
    ```
    
* char : PostgreSQL character(n) type에 해당된다.
    
    ```javascript
    import { char, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      char1: char(),
    });
    
    export const tableB = pgTable('table_b', {
      char2: char({ length: 256 }),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"char1" char,
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"char2" char(256),
    );
    ```
    
* numeric : PostgreSQL의 numeric type에 해당된다.
    
    ```javascript
    import { numeric, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      numeric1: numeric(),
    });
    
    export const tableB = pgTable('table_b', {
      numeric2: numeric({ precision: 100, scale: 20 }),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"numeric1" numeric,
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"numeric2" numeric(100, 20),
    );
    ```
    
* jsonb : PostgreSQL의 jsonb type에 해당된다.
    
    ```javascript
    import { jsonb, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
    	jsonb1: jsonb(),
    });
    
    export const tableB = pgTable('table_b', {
    	jsonb2: jsonb().default({ foo: "bar" }),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"jsonb1" jsonb,
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"jsonb2" jsonb default '{"foo": "bar"}'::jsonb,
    );
    ```
    
* time : PostgreSQL의 time type에 해당된다.
    
    ```javascript
    import { time, pgTable } from "drizzle-orm/pg-core";
    
    export const tableA = pgTable('table_a', {
      time1: time(),
    });
    
    export const tableB = pgTable('table_b', {
      time2: time({ withTimezone: true }),
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "table_a" (
    	"time1" time,
    );
    
    CREATE TABLE IF NOT EXISTS "table_b" (
    	"time2" time with timezone,
    );
    ```
    

위에서 살펴본 type은 사용할 수 있는 type의 일부이며 모든 type list는 documentation에서 확인할 수 있다. ( *Reference* - [PostgreSQL column types](https://orm.drizzle.team/docs/column-types/pg) )

## Identity Columns

drizzle schema를 생성할 때 `generatedByDefaultAsIdentity` method와 `generatedAlwaysAsIdentity` method를 통해 다음 두 type의 identity column을 생성할 수 있다.

* GENERATED ALWAYS AS IDENTITY : column의 value를 자동으로 생성한다. OVERRIDING SYSTEM VALUE절을 사용하지 않는 한 해당 column에 data를 직접적으로 추가하지 못한다.
    
* GENERATED BY DEFAULT AS IDENTITY : column의 value를 자동으로 생성하되 column에 data를 직접적으로 추가할 수도 있다.
    

```javascript
import { integer, pgTable, text } from "drizzle-orm/pg-core";

export const memberTable = pgTable("members", {
  id: integer().primaryKey().generatedAlwaysAsIdentity(),
  name: text(),
  email: text()
});
```

## Constraints

Table을 생성할 때 null을 허용하지 않는 column, 또는 테이블에서 값이 고유해야 하는 column등 여러 constraint을 column에 추가할 수 있는 값을 제한한다. drizzle schema를 생성할 때 각 column에 적용할 수 있는 constraint는 다음과 같다.

* not null : column의 not null constraint은 다음과 같이 설정할 수 있다.
    
    ```javascript
    import { pgTable, text } from "drizzle-orm/pg-core";
    
    export const memberTable = pgTable("members", {
      email: text().notNull()
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "members" (
      "email" text NOT NULL,
    );
    ```
    
* unique : column의 unique constraint는 다음과 같이 설정할 수 있다.
    
    ```javascript
    import { pgTable, text } from "drizzle-orm/pg-core";
    
    export const memberTable = pgTable("members", {
      email: text().unique('email_unique')
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "members" (
      "email" text NOT NULL,
      CONSTRAINT "email_unique" UNIQUE("email")
    );
    ```
    
* check : column의 check constraint는 다음과 같이 설정할 수있다.
    
    ```javascript
    import { pgTable, check, integer } from "drizzle-orm/pg-core";
    import { sql } from "drizzle-orm";
    
    export const memberTable = pgTable("members", {
      age: integer()
    },
    (table) => ({
        checkConstraint: check("check_age", sql`${table.age} > 20`),
     })
    );
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "members" (
        "age" integer,
        CONSTRAINT "check_age" CHECK ("members"."age" > 21)
    );
    ```
    
* Primary Key : column의 primary key는 다음과 같이 설정할 수 있다.
    
    ```javascript
    import { integer, pgTable, text } from "drizzle-orm/pg-core";
    
    export const memberTable = pgTable("members", {
      id: integer().primaryKey(),
      name: text()
    });
    ```
    
    위의 schema는 아래 SQL statement와 같다.
    
    ```sql
    CREATE TABLE IF NOT EXISTS "members" (
      "id" integer PRIMARY KEY,
      "name" text
    );
    ```
    
* Foreign Key : column의 foreign key는 다음과 같이 설정할 수 있다.
    
    ```javascript
    import { integer, pgTable, text } from "drizzle-orm/pg-core";
    
    export const author = pgTable("author", {
      id: integer().primaryKey(),
      name: text("name"),
    });
    
    export const memberTable = pgTable("book", {
      id: integer().primaryKey(),
      name: text(),
      authorId: integer("author_id_fkey").references(() => author.id)
    });
    ```
    
    위의 예제에서 book table은 author table id를 reference하는 authorId라는 foreign key를 생성한다.
    

위에서 살펴본 constraint외에 사용할 수 있는 다른 constraint도 있으며 모든 constraint list는 documentation을 통해 확인할 수 있다.

( *Documentation* - [Constraints](https://orm.drizzle.team/docs/indexes-constraints#constraints) )

## PostgreSQL Schema

만약 특정 postgreSQL schema에 소속된 drizzle table schema를 작성하고자 한다면 다음과 같이 `pgSchema`를 통해 설정할 수 있다. 아래 코드는 myschema라는 postgreSQL schema에 소속된 members table schema에 대한 예시다.

```typescript
import { integer, text, pgSchema } from "drizzle-orm/pg-core"

export const mySchema = pgSchema('myschema');

export const users = mySchema.table('members', {
  id: integer().primaryKey(),
  name: text()
})
```
