SQL Server を使っていると、
- 既存テーブルと同じ構造のテーブルを作りたい
- 一時テーブルやアーカイブテーブルをサクッと用意したい
- CREATE TABLE を手書きするのが面倒
という場面がよくあります。
そんなときに便利なのが SELECT TOP 0 * INTO です。
これは一言でいうと、
データは1件もコピーせず、テーブル構造だけ丸ごとコピーする方法
この記事では、実際に手を動かしながら 「なぜ * を使うのか?」 「何がコピーされて、何がコピーされないのか?」 「運用で気をつけるべき点は?」 までをまとめます。
1. 元テーブルを用意する
まずはサンプルとして在庫テーブルを作ります。
CREATE TABLE dbo.Zaiko (
ZaikoID INT IDENTITY(1,1),
ItemCode VARCHAR(20),
ItemName VARCHAR(100),
Quantity INT,
YM CHAR(6),
UpdatedAt DATETIME
);
CREATE INDEX IX_Zaiko_YM ON dbo.Zaiko(YM);データも少し入れておきます。
INSERT INTO dbo.Zaiko (ItemCode, ItemName, Quantity, YM, UpdatedAt)
VALUES
('A001', 'りんご', 100, '202401', '2024-01-10'),
('A002', 'みかん', 200, '202402', '2024-02-05'),
('A003', 'バナナ', 150, '202403', '2024-03-12'),
('A004', 'ぶどう', 180, '202404', '2024-04-03'),
('A005', 'メロン', 120, '202405', '2024-05-18'),
('A006', 'スイカ', 90, '202406', '2024-06-01'),
('A007', 'パイナップル', 75, '202407', '2024-07-22'),
('A008', 'キウイ', 60, '202408', '2024-08-09'),
('A009', '桃', 130, '202409', '2024-09-14'),
('A010', '梨', 110, '202410', '2024-10-02');

2. SELECT TOP 0 * INTO を実行する
Zaiko と同じ構造のテーブルを作りたい場合は、これだけです。
SELECT TOP 0 *
INTO dbo.Zaiko_Copy
FROM dbo.Zaiko;実行すると、Zaiko_Copy テーブルが新規作成されます。
3. 本当に「構造だけ」コピーされているか確認する
データ件数
SELECT COUNT(*) FROM dbo.Zaiko; -- 10件
SELECT COUNT(*) FROM dbo.Zaiko_Copy; -- 0件→ データはコピーされていません。

カラム構造
EXEC sp_help 'dbo.Zaiko';
EXEC sp_help 'dbo.Zaiko_Copy';→ カラム名・データ型・NULL制約・順番は完全一致。
dbo.Zaiko

dbo.Zaiko_Copy

4. SELECT TOP 0 * INTO の仕組み
この SQL はこう動きます。
INTO 新テーブル→ 新しいテーブルを作るTOP 0→ データは0件(=1件もコピーしない)*→ カラム構造をそのまま使う
結果として、
元テーブルと同じ構造の空テーブルが一瞬で作れる
というわけです。
5. あえて *(アスタリスク)を使う理由
✔ 理由1:カラム追加に強い
もしカラムを明示的に書くと、 新しいカラムが追加されるたびに書き直しが必要です。
SELECT TOP 0 ZaikoID, ItemCode, ... ← 毎回修正が必要しかし * を使えば、
SELECT TOP 0 * INTO Zaiko_Copy FROM Zaiko;→ カラム追加しても自動で反映される → ストアドやアプリ側の修正が不要
運用が圧倒的に楽になります。
✔ 理由2:カラム順まで完全一致する
INSERT … SELECT * を使う処理では、 カラム順が一致していることが前提です。
- を使えば順番も完全一致するため、 アーカイブ処理などで安全に利用できます。
✔ 理由3:CREATE TABLE を手書きするより安全
手書きの CREATE TABLE は、
- カラム名のタイプミス
- データ型の書き間違い
- NULL / NOT NULL のミス
など、事故の温床です。
SELECT TOP 0 * INTO なら 100% 正確にコピー できます。
6. 何がコピーされて、何がコピーされないのか?
コピーされるもの
- カラム名
- データ型
- NULL / NOT NULL
- カラム順
コピーされないもの(重要)
- インデックス(非クラスタード含む)
- PRIMARY KEY
- UNIQUE
- FOREIGN KEY
- CHECK
- DEFAULT
つまり、SELECT TOP 0 * INTO は「構造だけコピーする」 ということです。
7. インデックスがコピーされないことを確認する
EXEC sp_helpindex 'dbo.Zaiko';
EXEC sp_helpindex 'dbo.Zaiko_Copy';dbo.Zaikoはインデックスが設定されている。

dbo.Zaiko_Copyにはインデックスの設定がなくなっている。

結果:
- Zaiko → IX_Zaiko_YM が存在
- Zaiko_Copy → インデックスなし
→ インデックスはコピーされません。
必要なら後から追加します。
CREATE INDEX IX_Zaiko_Copy_YM ON dbo.Zaiko_Copy(YM);8. アーカイブ環境などで運用で必ず覚えておくべき注意点
この方法でコピーテーブルを作成するのは、アーカイブやバックアップテーブルを作るときなどが考えられます。
🔥 元テーブルにカラムを追加したら👉 アーカイブテーブルにも同じカラムを追加する必要がある
SELECT TOP 0 * INTO は「最初に作るとき」は便利ですが、 元テーブルにカラムを追加しても、コピーしたテーブルには自動で増えません。アーカイブなどの運用では注意が必要です。
例:
ALTER TABLE Zaiko ADD Location VARCHAR(20);この場合、アーカイブ側も手動で追加します。
ALTER TABLE Zaiko_Archive ADD Location VARCHAR(20);これを忘れると:
- SELECT * のカラム数がズレる
- アーカイブ処理がエラーになる
という事故につながります。
9. SELECT TOP 0 * INTO が便利な場面
- アーカイブテーブルの作成
- 一時テーブルの作成
- 作業用テーブルの作成
- 元テーブルとほぼ同じ構造のテーブルを作りたいとき
- CREATE TABLE を手書きしたくないとき
- カラム追加に強い仕組みを作りたいとき
まとめ
- SELECT TOP 0 * INTO は 構造だけコピーする魔法の SQL
- データはコピーされない
- インデックス・制約はコピーされない
- あえて * を使うことで「カラム追加に強い」テーブルが作れる
- ただし 元テーブルにカラムを追加したら、アーカイブ側にも追加が必要
- アーカイブや一時テーブルで大活躍


コメント