CREATE TABLE(表を作る)の使い方
できた表 mokuhyou
| 列 | 型 | NULL | 制約 |
|---|---|---|---|
| busho_id | integer | 不可 | 主キー |
| kingaku | numeric(10,0) | 不可 | |
| memo | text | 可 |
この表は文を実際に流して作り、データベース自身が持つ表の情報を読んで描いています。int と書いた列の型が integer になり、PRIMARY KEY と書いただけの busho_id が NULL 不可になっていることに注目してください。書いたことと、実際に付く定義は同じではありません。
CREATE TABLE は、これから入る値の約束を決める文です。 列の名前と型を並べるだけでなく、NOT NULL・既定値・主キー・外部キーを書いておくと、おかしなデータが入る前にデータベースが止めてくれます。⚠️ ここで決めたことはあとから変えにくい——データが入ってから型を変えるのは移行作業になります。
この書き方が使えない製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite
- SQL Server では使えません(問い合わせの結果から表を作る(CREATE TABLE ... AS SELECT))
- Oracle Database では使えません(text 型の列) / この問題のほかの構文は未確認です
未確認: IBM Db2
このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。
01列の名前と型を決める
結論: CREATE TABLE 表名 (列名 型, 列名 型, …) で表ができます。
型は「その列に入れてよい値」の約束です。数を入れる列に文字の型を選ぶと、あとで合計や比較ができません。逆に、電話番号や郵便番号のように計算しない数字は文字の型にします(先頭の 0 が消えるため)。
金額には numeric を使ってください。桁数と小数点以下の桁を指定でき、丸め方が決まっているためです。real や double precision は速い代わりに誤差が出るので、お金には向きません。
⚠️ 型の名前は製品で違います。 PostgreSQL の text は Oracle には無く、VARCHAR2 や CLOB になります。int のような標準的な型はだいたい通ります。
CREATE TABLE mokuhyou (作る表の名前busho_id int PRIMARY KEY,★列名・型・制約の順に書くkingaku numeric(10,0) NOT NULL,★桁を指定できる型memo text最後の列にカンマは付けない);括弧を閉じて終わり
列と列はカンマで区切ります。最後の列のうしろにカンマを書くとエラーになるので、行を足し引きしたときによく落とします。
CREATE TABLE mokuhyou (
busho_id int PRIMARY KEY,
kingaku numeric(10,0) NOT NULL,
memo text
);
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'mokuhyou'
ORDER BY ordinal_position;| column_name | data_type | is_nullable |
|---|---|---|
| busho_id | integer | NO |
| kingaku | numeric | NO |
| memo | text | YES |
(3 行)
information_schema はデータベース自身が持つ「表の情報」です。書いた int が integer になり、PRIMARY KEY を書いた busho_id は is_nullable が NO になっています。
⚠️ この書き方は Oracle Database では使えません(text 型の列)。製品ごとの対応表
02NOT NULL と既定値は別のもの
結論: NOT NULL は「NULL を入れさせない」、DEFAULT は「書かなかったときに何を入れるか」です。
この 2 つはよく混同されますが、守っているものが違います。既定値だけを付けた列は、INSERT で明示的に NULL を渡せば NULL が入ります。「必ず値がある」を保証したいなら、既定値とは別に NOT NULL を付けてください。
逆に NOT NULL だけを付けて既定値を書かないと、その列を省いた INSERT はエラーになります。毎回書かせたいのか、省けるようにしたいのかで決めます。
⚠️ NULL は「0」でも「空文字」でもなく、値が無いことです。合計や比較の対象から外れるので、集計が合わない原因になります。
CREATE TABLE mokuhyou (
busho_id int PRIMARY KEY,
kingaku numeric(10,0) NOT NULL DEFAULT 0,
memo text
);
INSERT INTO mokuhyou (busho_id) VALUES (2);
SELECT busho_id, kingaku, memo FROM mokuhyou;| busho_id | kingaku | memo |
|---|---|---|
| 2 | 0 | NULL |
(1 行)
kingaku を書かなかったので既定値の 0 が入りました。memo は既定値を決めていないので NULL です。「書かなかった」の結果が列によって違うことが分かります。
⚠️ この書き方は Oracle Database では使えません(text 型の列)。製品ごとの対応表
CREATE TABLE mokuhyou (
busho_id int PRIMARY KEY,
kingaku numeric(10,0) NOT NULL DEFAULT 0
);
INSERT INTO mokuhyou (busho_id, kingaku) VALUES (2, NULL);「null value in column "kingaku" … violates not-null constraint」で落ちます。既定値が効くのは列を書かなかったときだけで、NULL と書けば NULL を入れようとします。
03⚠️ よくある間違い:主キーと外部キーで、おかしなデータを止める
結論: PRIMARY KEY は「行を 1 つに決める列」、REFERENCES は「相手の表に実在する値だけを許す」です。
主キーを書くと、重複した値も NULL も入らなくなります(NOT NULL を書かなくても付きます)。外部キーを書くと、相手の表に無い値を入れようとしたときにデータベースが拒否します。アプリ側の検査を忘れても、最後の砦になります。
⚠️ 外部キーを付けると、参照されている親の行を消せなくなります(既定は拒否)。消し方まで決めてから付けてください。
⚠️ 外部キーが指す相手の列には、主キーか一意制約が必要です。ただの列は指せません。
できた表 mokuhyou
| 列 | 型 | NULL | 既定値 | 制約 |
|---|---|---|---|---|
| busho_id | integer | 不可 | — | 主キー・外部キー → busho.busho_id・親を消せない |
| kingaku | numeric(10,0) | 不可 | 0 | |
| memo | text | 可 | — |
busho_id には主キーと外部キーが両方付いています。NOT NULL と書いていないのに NULL 不可になっているのは、主キーだからです。
CREATE TABLE mokuhyou (
busho_id int PRIMARY KEY REFERENCES busho(busho_id),
kingaku numeric(10,0) NOT NULL DEFAULT 0
);
INSERT INTO mokuhyou (busho_id) VALUES (99);「violates foreign key constraint」で落ちます。busho に 99 番の部署が無いためです。入る前に止まるので、あとから辻褄合わせをしなくて済みます。
04問い合わせの結果から表を作る
結論: CREATE TABLE 表名 AS SELECT … で、問い合わせの結果をそのまま表にできます。
列の名前と型は SELECT から受け継ぎます。集計した結果を取っておきたいときや、作業用の表がほしいときに便利です。
⚠️ 制約は引き継ぎません。 元の表で主キーや NOT NULL が付いていた列でも、この書き方で作った表では NULL 可のただの列になります。必要なら作ったあとで ALTER TABLE で足します。
⚠️ 元の表が変わっても追随しません。 作った時点の写しなので、常に最新にしたいならビューを使ってください。
できた表 zaiseki
| 列 | 型 | NULL | 制約 |
|---|---|---|---|
| shain_id | integer | 不可 | |
| name | text | 可 | |
| salary | numeric(10,0) | 可 |
型は shain から受け継いでいますが、主キーは付いていません。ここでは ALTER TABLE で shain_id にだけ NOT NULL を足しています。制約は自分で足すもの、と覚えてください。
CREATE TABLE zaiseki AS
SELECT shain_id, name, salary
FROM shain
WHERE taishoku_on IS NULL;
SELECT count(*) AS kensu FROM zaiseki;| kensu |
|---|
| 16 |
(1 行)
18 人のうち在籍中の 16 人だけが入りました。WHERE で絞った結果が、そのまま新しい表になります。
⚠️ この書き方は SQL Server では使えません(問い合わせの結果から表を作る(CREATE TABLE ... AS SELECT))。製品ごとの対応表
自分で打ってみる
このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。
押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。
解いてみる
読んだだけでは書けるようになりません。実行結果で採点します。
関連するトピック
根拠(一次情報)
- PostgreSQL 18 マニュアル: CREATE TABLE一次情報・確認 2026-09-02
- PostgreSQL 18 マニュアル: 制約(主キー・外部キー・CHECK)一次情報・確認 2026-09-02
- PostgreSQL 18 マニュアル: データ型一次情報・確認 2026-09-02
- PostgreSQL 18 マニュアル: CREATE TABLE AS一次情報・確認 2026-09-02