自分用まとめ
RDBMS の主要製品とそのお試しを書いていて、気づいたのでメモ
お約束
間違いが含まれる可能性がそこそこあります。
間違いを見つけたら「どこを」「どのように」修正すべきか教えてください。
やりたいこと
あるテーブルに対し、一度の INSERT 文で複数の行を挿入したい。
設定
このようなテーブルを作る。
ID | NAME | AGE |
---|
CREATE TABLE Students (
id INT PRIMARY KEY,
name VARCHAR(16),
age INT
);
INSERT するコード
MySQL 等
INSERT INTO Students VALUES
(1, 'Alice', 16),
(2, 'Bob', 18),
(3, 'Charlie', 15),
(4, 'David', 23);
MySQL でも PostgreSQL でも SQL Server でもこれでできる。
が、この書き方はOracle DataBase ではできない…
Oracle Database
INSERT ALL -- ここに ALL がつく
INTO Students VALUES (1, 'Alice', 16) -- 行末にカンマをつけないこと!
INTO Students VALUES (2, 'Bob', 18) -- カンマをつけると、
INTO Students VALUES (3, 'Charlie', 15) -- ORA-00928: missing SELECT keyword
INTO Students VALUES (4, 'David', 23) -- となります
SELECT * FROM DUAL;
1つずつ INSERT INTO
するのとほぼ変わらないやん…(絶望)
この構文は、ある表から SELECT して別の表へ INSERT する時の書き方がベースになっているように見える。
ただし、今回は元の表が無いので、元の表を指定する部分は SELECT * FROM DUAL
として省略している。
(SELECT 1 FROM DUAL
とかにしても動く。何を SELECT するかはどうでもいいらしい)
逆に、この書き方は、MySQL 等ではエラーとなる。
「この書き方ならどの製品でも動く」という書き方はないらしい?
余談
MySQL等の書き方は、「1つのテーブルに複数の行を挿入」するものであるが、
Oracle Database の書き方は「テーブルを指定した INSERT を複数行う」というイメージ。
つまり、Oracle では異なる複数のテーブルに対して一度に INSERT することもできる。
-- DROP TABLE Students;
-- DROP TABLE Evaluations;
CREATE TABLE Students (
id INT PRIMARY KEY,
name VARCHAR(16),
age INT
);
CREATE TABLE Evaluations (
name VARCHAR(16),
subject VARCHAR(16),
score INT,
PRIMARY KEY(name, subject)
);
INSERT ALL -- Students と Evaluations へ INSERT
INTO Students VALUES (1, 'Alice', 16)
INTO Students VALUES (2, 'Bob', 18)
INTO Evaluations VALUES ('Alice', 'english', 30)
INTO Evaluations VALUES ('Alice', 'math', 60)
INTO Evaluations VALUES ('Bob', 'english', 40)
INTO Evaluations VALUES ('Bob', 'math', 80)
SELECT * FROM DUAL;
検証環境
$ mysql --version
mysql Ver 8.0.26 for macos11.4 on arm64 (Homebrew)
$ psql --version
psql (PostgreSQL) 12.7
Oracle は LiveSQL を使用。
その他、SQL Server 15.0.2000 でも検証。