技術資料

MySQLのCREATE TABLE LIKEでテーブル構造をコピーする:使い方と注意点

作成日:2026.10.16

MySQLのCREATE TABLE LIKEで、既存テーブルの構造を基に空テーブルを作る方法を解説します。列やインデックスの確認、外部キーが引き継がれない点に加え、INSERT SELECTによるデータのコピー方法も紹介します。

既存のテーブルを基に、テスト用のテーブルを別の名前で作りたいことは多々あると思います。列やインデックスを一つずつ書き直すのは面倒ですが、MySQLではCREATE TABLE … LIKEで構造を使い回せます。

この構文、便利ですね。最近まで知らなかったので、知った時には便利さに恐れおののきました。今回は、基本の使い方と、コピーされるもの・されないものを整理します。データもコピーしたい場合の方法は、後半で補足します。

CREATE TABLE … LIKEの基本

基本的な書き方は次のとおりです。

CREATE TABLE new_table LIKE original_table;

new_tableが作成するテーブル名、original_tableが元のテーブル名です。元のテーブルにある列の型、NOT NULL、既定値、主キーやインデックスなどの定義を基に、新しいテーブルを作成します。

ここで作られるのは、データが入っていない空のテーブルです。元のテーブルに何万件のデータがあっても、その行がコピーされるわけではありません。構文の詳細は、MySQL公式のCREATE TABLE … LIKEの説明を参照してください。

小さなテーブルで試す

例えば、本番と同じ構造のテーブルをテスト用に用意したい場面で使えます。ここでは本番DBへ接続せず、検証用DBに作った説明用のテーブルで流れを示します。

Workbenchで専用の検証用DBを選択し、次のテーブル名がまだ使われていないことを確認してください。各SQLは作成・追加が成功したことを確認しながら順に実行します。接続や実行範囲の操作は、MySQL Workbench入門の記事も参照してください。

まず、元になるテーブルを作ります。

CREATE TABLE like_demo_products (
    id INT UNSIGNED NOT NULL,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    PRIMARY KEY (id),
    KEY idx_price (price)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

主キーのほかに、price列のインデックスと既定値を付けています。続けて、説明用のデータを2件追加します。このINSERTは一度だけ実行してください。

INSERT INTO like_demo_products (id, name, price)
VALUES
    (1, 'Keyboard', 3000.00),
    (2, 'Cable', 800.00);

次の1文で、同じ構造を基にしたテーブルを別の名前で作れます。

CREATE TABLE like_demo_products_test LIKE like_demo_products;

列の定義をもう一度書かなくてよいのは、ありがたいですね。元のテーブルの名前やデータが、この操作で変更されることもありません。

構造と行数を確認する

構造の確認には、SHOW CREATE TABLEを使います。

SHOW CREATE TABLE like_demo_products;
SHOW CREATE TABLE like_demo_products_test;

Workbenchの結果にあるCreate Table列で、それぞれの定義を比べてみます。今回の例では、次の項目が作成先にもあることを確認します。

  • id、name、priceの列と、それぞれの型・NOT NULL指定
  • priceの既定値0.00
  • idのPRIMARY KEY
  • priceのインデックスidx_price

テーブル名は異なるので、表示されるCREATE TABLE文全体が同じ文字列になるわけではありません。必要な列やインデックスがあるかを見ると分かりやすいです。

行数は次のSELECTで比較できます。

SELECT 'original' AS table_role, COUNT(*) AS row_count
FROM like_demo_products
UNION ALL
SELECT 'test' AS table_role, COUNT(*) AS row_count
FROM like_demo_products_test
ORDER BY table_role;

ここまでのSQLを一度ずつ実行した場合の期待結果です。

table_rolerow_count
original2
test0

元には2件あっても、作成先は0件です。構造のコピーとデータのコピーが別であることが分かります。

外部キー定義はコピーされない

CREATE TABLE … LIKEでは、すべての定義がそのまま引き継がれるわけではありません。特に注意したいのが、外部キー定義です。

対象作成先への引き継ぎ
列の型・NOT NULL・既定値引き継がれる
主キー・インデックス引き継がれる
保存されているデータコピーされない
外部キー定義引き継がれない

例えば、元のテーブルがcategory_id列でカテゴリテーブルを参照していても、作成先にその外部キー制約は付きません。列やインデックスが存在することと、参照先との整合性を検査する制約が存在することは別問題です。

外部キーを含む動作をテストしたい場合は、SHOW CREATE TABLEで確認したうえで、テスト用の参照先に合わせて制約を追加する必要があります。構造を使い回せる便利な構文ですが、必要な定義までそろっているかは確認しておきましょう。

補足:データもコピーしたい場合

作成した空テーブルへデータも入れたい場合は、続けてINSERT … SELECTを使えます。今回の例なら、次のようにコピーする列を明示します。

INSERT INTO like_demo_products_test (id, name, price)
SELECT id, name, price
FROM like_demo_products;

空の作成先へ一度だけ実行した場合、2件が追加される想定です。同じSQLを再実行すると、今回の定義ではidが重複するためエラーになります。コピー後は次のSELECTで内容を確認できます。

SELECT id, name, price
FROM like_demo_products_test
ORDER BY id;

期待結果は、idが1のKeyboardとidが2のCableの2行です。必要な行だけをコピーするなら、SELECT側にWHERE条件を付ける方法もあります。詳しくは、MySQL公式のINSERT … SELECTの説明を参照してください。

本番由来のデータをテストに使う場合は、個人情報などをそのまま持ち込まず、マスキングや説明用データへの置き換えを検討しましょう。また、大量データのコピーは負荷やロックの影響を確認してから行いましょう。

使うときの注意点

  • コピー元を参照するSELECT権限と、作成先にテーブルを作るCREATE権限が必要です。データも追加する場合は、作成先のINSERT権限も確認しましょう。
  • 作成先に同名テーブルがあるとエラーになります。名前と接続先を確認し、作成に失敗したまま後続のINSERTへ進まないようにしましょう。
  • CREATE TABLE … LIKEのコピー元はテーブルです。ビューを指定する用途には使えません。
  • コピー元の作成時と現在のSQLモードが異なると、定義の検査で失敗する場合があります。

構造だけならCREATE TABLE … LIKE、データも必要なら続けてINSERT … SELECT。まずは小さなテーブルで定義と行数を比較すると、使いどころをつかみやすいかと思います。

この記事を書いた人

※上が私です。

奈良市を拠点に、27年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。

これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。

【制作会社・企業様向けサポート】
  • 専任エンジニアのいない企業様に対するシステム面の不安を解消
  • 柔軟な契約形態や短納期での対応により、急なニーズにも迅速にサポート
  • システムの企画段階から運用まで、ワンストップでのサービスを提供

Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。

ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。

MySQLのビュー(VIEW)入門:テーブルとの違いと使いどころ

2026.10.18

MySQLのビュー(VIEW)とテーブルの違い、ビューが役立つ場面を解説します。CREATE VIEWによる作成方法を、注文データの抽出・集計例で紹介。元データの変更との関係や、更新・性能・参照権限の注意点も整理します。

MySQL

MySQLの正規表現でタイムアウト(Error Code 3699)が発生する原因と対処法

2026.10.17

MySQLの正規表現で発生する「Error Code 3699」の原因と対処法を解説します。SQLやパターンの見直し、一時テーブルを使った検索と整形の分離、最終手段としてのregexp_time_limitの変更と注意点を紹介します。

MySQL 正規表現

MySQLのDATE_FORMATとTIME_TO_SEC:日時の表示と時間の数値化

2026.10.13

MySQLのDATE_FORMATで日時の表示を整える方法と、TIME_TO_SECで時間を秒数へ変換する方法を解説します。入力と結果を比較しながら、月と分の書式指定、NULL、負の時間、24時間を超える時間の扱いも紹介します。

MySQL

MySQLのCASE式入門:条件に応じてSELECTの出力を切り替える

2026.10.12

MySQLのCASE式を使い、条件に応じてSELECTの出力値を切り替える方法を解説します。状態コードを表示名に変換する例を通して、基本構文、ELSEとNULLの扱い、条件が重なる場合のWHENの順序を紹介します。

MySQL

阿部辰也へのお仕事の依頼・お問い合わせ

軽いご相談もお気軽にどうぞ!

個人情報の取り扱いについて *必須 プライバシーポリシーをご確認いただき、同意いただける場合は「同意する」にチェックをしてください。

keyboard_double_arrow_up
TOP