テーブルの作成後、INSERT ステートメントまたはその他のステートメントを使用して、テーブルにレコードを挿入できます。本記事では、関連するステートメントの使い方と例を紹介します。
データ挿入の準備
データを挿入する前に、以下の項目を確認してください:
データベースのMySQLテナントに接続していることを確認してください。データベースへの接続操作については、接続方法の概要を参照してください。
説明
現在ログインしているテナントが属するテナントモードは、
sysテナントでoceanbase.DBA_OB_TENANTSビューをクエリすることで確認できます。操作対象のテーブルの
INSERT権限を持っていることを確認してください。現在のユーザー権限を確認する操作の詳細については、ユーザー権限の確認を参照してください。この権限を持っていない場合は、管理者に連絡し権限の付与を依頼してください。ユーザー権限に関する操作については、直接権限付与を参照してください。
INSERT INTOステートメントを使用したデータの挿入
INSERT ステートメントを使用し、下記の提案を参考にしてテーブルにデータを挿入してください。
INSERT INTO ステートメントの構文は以下のとおりです:
INSERT INTO table_name [(list_of_columns)] VALUES (list_of_values);
| パラメータ | 必須 | 説明 |
|---|---|---|
| table_name | はい | データを挿入するテーブルを指定します |
| (list_of_columns) | いいえ | テーブル内でデータを挿入する列を指定します |
| (list_of_values) | はい | list_of_columns に記載されている列に対応する値で、1対1対応である必要があります。 |
データの挿入に関する推奨事項
データを挿入する前に、列のタイプ、有効な値、NULLを許容するかどうかなど、テーブルのすべての列情報について確認することを推奨します。
列情報は
DESCステートメントで確認できます。obclient [test]> DESC test; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | col1 | int(11) | NO | | NULL | | | col2 | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set列属性が
NOT NULLの場合列属性にデフォルト値が設定されている場合、挿入時にその列の値を指定しなくても、システムがその列にデフォルト値を挿入します。
列属性にデフォルト値が設定されていない場合、挿入時にはその列の値を指定する必要があります。
列属性が
NULLの場合、挿入時にその列の値を指定しなくても、システムがその列にNULL値を挿入します。
データを挿入する前に、テーブルの列の制約定義を確認し、データ挿入時のエラーを避けることを推奨します。
NOT NULL、PRIMARY KEY制約、UNIQUE制約はすべてDESCステートメントで確認することができます。FOREIGN KEY、CHECK制約は、information_schema.TABLE_CONSTRAINTSビューをクエリすることで確認することができます。
単一行データの挿入
INSERT ステートメントを使用することで、単一行のデータを挿入できます。複数のレコードを挿入する必要がある場合は、複数の単一行挿入ステートメントを実行することで対応できます。一括挿入が必要な場合は、複数行データの一括挿入 を参照して操作することができます。
データを挿入するテーブルの想定情報は以下のとおりです:
obclient [test]> CREATE TABLE t_insert(
id int NOT NULL PRIMARY KEY,
name varchar(10) NOT NULL,
value int,
gmt_create DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Query OK, 0 rows affected
この中で、テーブルの id 列と name 列は空欄にすることができず、id 列は主キーであるため、一意性制約の要件を満たす必要があり、重複する値を持つことはできません。gmt_create 列にはデフォルト値が設定されています。
例1:複数の単一行挿入ステートメントを使用して、複数行のデータを挿入します。
gmt_create 列にはデフォルト値が指定されているため、データ挿入時にデフォルト値を指定する必要はありません。
obclient [test]> INSERT INTO t_insert(id, name, value)
VALUES (1,'CN',10001);
Query OK, 2 rows affected
obclient [test]> INSERT INTO t_insert(id, name, value)
VALUES(2,'US', 10002);
Query OK, 2 rows affected
注意:gmt_create 列にデフォルト値が指定されていない場合、データ挿入時に値を指定し、以下のステートメントを使用する必要があります。
obclient [test]> INSERT INTO t_insert(id, name, value, gmt_create)
VALUES (3,'EN', 10003, current_timestamp ());
Query OK, 1 row affected
複数行データの一括挿入
データ挿入時に、複数のレコードを挿入する必要がある場合は、1つの INSERT ステートメントに複数の VALUES を含めて、一括挿入を行うこともできます。単一の複数行挿入ステートメントは、複数の単一行挿入ステートメントよりも高速です。
例1の操作は、以下のステートメントでも実行できます。
例2:複数行データを一括挿入します。
obclient [test]> INSERT INTO t_insert(id, name, value)
VALUES (1,'CN',10001),(2,'US', 10002);
Query OK, 2 rows affected
さらに、テーブルデータのバックアップが必要な場合、またはテーブルのすべてのレコードを別のテーブルにコピーする必要がある場合、INSERT INTO ... SELECT ... FROM クエリを使用して、INSERT の values 句として一括挿入を実行できます。
例3:テーブル t_insert の全データを t_insert_bak テーブルにバックアップします。
obclient [test]> SELECT * FROM t_insert;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2022-10-12 15:17:17 |
| 2 | US | 10002 | 2022-10-12 16:29:16 |
| 3 | EN | 10003 | 2022-10-12 16:29:26 |
+----+------+-------+---------------------+
3 rows in set
obclient [test]> CREATE TABLE t_insert_bak(
id number NOT NULL PRIMARY KEY,
name varchar(10) NOT NULL,
value number,
gmt_create DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Query OK, 0 rows affected
obclient [test]> INSERT INTO t_insert_bak SELECT * FROM t_insert;
Query OK, 2 rows affected
obclient [test]> SELECT * FROM t_insert_bak;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2022-10-12 15:17:17 |
| 2 | US | 10002 | 2022-10-12 16:29:16 |
| 3 | EN | 10003 | 2022-10-12 16:29:26 |
+----+------+-------+---------------------+
3 rows in set
一意性制約違反の回避
テーブルに一意性制約が設定されている場合、同じレコードを挿入しようとすると、データベースはエラーを報告します。エラーメッセージは以下のとおりです:
obclient [test]> INSERT INTO t_insert(id, name, value) VALUES (3,'UK', 10003),(4, 'JP', 10004);
ERROR 1062 (23000): Duplicate entry '3' for key 'PRIMARY'
このエラーは、INSERT IGNORE INTO ステートメントまたは INSERT INTO ON DUPLICATE KEY UPDATE ステートメントを用いることで回避できます。
例:
INSERT IGNORE INTOステートメントで制約違反を回避する場合、IGNOREキーワードは制約違反によってINSERTが失敗した際の影響を無視させることができます。
obclient [test]> INSERT IGNORE INTO t_insert(id, name, value)
VALUES (3,'UK', 10003),(4, 'JP', 10004);
Query OK, 1 row affected
obclient [test]> SELECT * FROM t_insert;
+----+------+-------+---------------------+
| id | name | value | gmt_create |
+----+------+-------+---------------------+
| 1 | CN | 10001 | 2022-10-12 15:17:17 |
| 2 | US | 10002 | 2022-10-12 16:29:16 |
| 3 | EN | 10003 | 2022-10-12 16:29:26 |
| 4 | JP | 10004 | 2022-10-12 17:02:52 |
+----+------+-------+---------------------+
4 rows in set
例では、INSERT IGNORE INTO ステートメントが使用されています。(3,'UK', 10003) 行のデータ挿入に失敗しましたが、システムはエラーを報告しませんでした。
INSERT INTO ON DUPLICATE KEY UPDATEステートメントで制約違反を回避する場合、重複する主キーまたは一意キーに対する後続の処理を指定することができます。説明
ON DUPLICATE KEY UPDATE column_name = exprを指定する場合:挿入しようとする主キーまたは一意キーが重複する場合、代入ステートメントcolumn_name = exprを用いてテーブル内で競合する行のデータを更新することができます。 代入ステートメントcolumn_name = exprを用いて、競合する行に特定の1列または複数の列の値を割り当てることができます。複数の列の値を割り当てる場合、列と列の間をカンマ(,)で区切ります。ON DUPLICATE KEY UPDATE column_name = exprを指定しない場合:挿入しようとする主キーまたは一意キーが重複する場合、データの挿入時にシステムはエラーを報告します。
obclient [test]> INSERT INTO t_insert(id, name, value) VALUES (3,'UK', 10003),(5, 'CN', 10005) ON DUPLICATE KEY UPDATE name = VALUES(name); Query OK, 1 row affected obclient [test]> SELECT * FROM t_insert; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2022-10-12 16:29:16 | | 2 | US | 10002 | 2022-10-12 15:17:17 | | 3 | UK | 10003 | 2022-10-12 16:29:26 | | 4 | JP | 10004 | 2022-10-12 17:02:52 | | 5 | CN | 10005 | 2022-10-12 17:27:46 | +----+------+-------+---------------------+ 5 rows in set例中の
ON DUPLICATE KEY UPDATE name = VALUES(name)は、挿入するデータがテーブルの主キー値と重複する場合、テーブルの競合する行の元のデータ(3,'EN', 10003)のname列の値を、現在挿入しようとしているname列のデータに更新することを意味します。他の競合しない行は、正常に挿入されます。
INSERT OVERWRITE SELECTステートメントを使用してデータを挿入する
INSERT OVERWRITE SELECT ステートメントは、クエリの結果でテーブルまたはパーティション内の既存データを置き換え、クエリで取得したデータをターゲットテーブルまたはパーティションに上書きすることができます。
このステートメントの構文は以下のとおりです:
INSERT [/*+PARALLEL(N)*/] OVERWRITE table_name [(list_of_columns)] [PARTITION (partition_name, ...)] select_stmt;
| パラメータ | 説明 |
|---|---|
| PARALLEL(N) | オプション、上書き書き込み操作のパラレル実行度を指定します。指定されていない場合、デフォルトの並列度は2です。 |
| table_name | 挿入先のテーブル名を指定します。 |
| list_of_columns | テーブル内でデータを挿入する列を指定します。 |
| select_stmt | SELECT 句を指定します。クエリステートメントの詳細については、SELECTステートメントを参照してください。 |
| partition_name | 挿入テーブルで指定されたパーティション名。複数のパーティションを挿入する場合は、カンマ(,)で区切ります。 |
INSERT OVERWRITE SELECTの使用制限
テーブルレベルのINSERT OVERWRITE SELECTの使用制限
- このステートメントは、複数行トランザクションでは操作できません。そのため、操作をスムーズに実行するために、まず
SET autocommit = on;コマンドを実行して自動トランザクションコミットモードを有効にする必要があります。 - 書き込み対象のテーブルにテーブルロックがかかります。同じテーブルに対してDDL操作を同時に実行することは許可されず、同時に実行されたDML操作はテーブルロックが解放されるまでタイムアウトするまで待機します。操作中にテーブルに対してクエリを実行することは可能です。
- このステートメントが操作するソースデータと、ターゲットテーブルで上書きされる列の数は、厳密に一致している必要があります。一致しない場合はエラーが発生します。
- このステートメントのデータ書き込み操作は、フル・ダイレクトロード方式を採用しているため、操作はフル・ダイレクトロード機能の制限を受けます。ダイレクトロードに関する情報は、INSERT INTO SELECTステートメントによるデータのダイレクトロード の 使用上の制限 セクションを参照してください。
- このステートメントは、ダイレクトロードのヒントを指定するとエラーが発生します。
- PDML(Parallel Data Manipulation Language、並列データ操作言語)フレームワークの制限により、PDMLでサポートされていないシナリオではデータのインポートができません。
INSERT OVERWRITE SELECTは、「not supported」エラーを報告をします。並列DMLの詳細については、並列DMLを参照してください。
パーティションレベルのINSERT OVERWRITE SELECT
機能紹介
- ソーステーブルはパーティションテーブルでも非パーティションテーブルでも構いません。パーティショニングタイプに制限はありません。
- ターゲットテーブルは、パーティションまたはサブパーティションをサポートします。
- ターゲットテーブルはローカルインデックスとLOBをサポートしています。
- ターゲットテーブルのすべてまたは一部のパーティションを指定できます。ターゲットテーブルにサブパーティションがある場合は、パーティションとサブパーティションを個別または混合して指定できます。
- 指定されたターゲットテーブルのパーティションにソーステーブルからのデータがヒットしない場合、そのパーティションのデータはクリアされます(空データで上書きされます)。
- OceanBaseデータベースV4.3.5 BP1バージョンから、パーティションレベルの
insert overwrite操作は、ターゲットテーブルの最後のレベルのパーティションがHashまたはKeyのパーティションであることをサポートします。
使用制限
- 指定されたパーティションは既に存在している必要があります。そうでない場合、エラーが発生します。
- フルダイレクトロードに基づいており、
/*+ append */ヒントを追加する必要はありません。そうしないと、使用時にエラーが発生します。 - このステートメントは、複数行トランザクションでは操作できません。そのため、操作をスムーズに実行するために、まず
SET autocommit = on;コマンドを実行して自動トランザクションコミットモードを有効にする必要があります。 - ソーステーブルからのデータがターゲットテーブルのパーティションルールに従って計算された後、指定されたターゲットテーブルのパーティションにヒットしない場合、パーティションが存在しないというエラーが発生します。
- 現在、ターゲットテーブルに自動インクリメント列はサポートされていません。
- 現在、ターゲットテーブルにグローバルインデックスまたは外部キーはサポートされていません。
- 現在、ターゲットテーブルとして外部テーブルはサポートされていません。
INSERT OVERWRITE SELECTの例
例1
テストテーブルを2つ作成します:
source_tbl1をデータソースとし、target_tbl1をターゲットテーブルとします。CREATE TABLE source_tbl1 (col1 INT, col2 VARCHAR(20), col3 INT);CREATE TABLE target_tbl1 (col1 INT, col2 VARCHAR(20), col3 INT);source_tbl1テーブルにサンプルデータを追加します。INSERT INTO source_tbl1 VALUES (1, 'A1', 30),(2, 'B2', 25),(3, 'C3', 22);target_tbl1テーブルにサンプルデータを追加します。INSERT INTO target_tbl1 VALUES (4, 'D4', 35),(5, 'E5', 28);target_tbl1テーブルからデータをクリエします。SELECT * FROM target_tbl1;実行結果は次のとおりです:
+------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 4 | D4 | 35 | | 5 | E5 | 28 | +------+------+------+ 2 rows in setINSERT OVERWRITE SELECTステートメントを使用して、col3が25より大きいデータをsource_tbl1から選択し、それらのデータをtarget_tbl1に挿入して、既存の内容を置き換えます。INSERT OVERWRITE target_tbl1 SELECT * FROM source_tbl1 WHERE col3 > 25;target_tbl1テーブルの置き換え後のデータを確認します。SELECT * FROM target_tbl1;実行結果は次のとおりです:
+------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 1 | A1 | 30 | +------+------+------+ 1 row in set
例2
INSTER OVERWRITE PARTITION SELECT の使用例:
パーティションテーブル
t1_ins_overwrtを作成します。obclient> CREATE TABLE t1_ins_overwrt (c1 int primary key, c2 int) partition by range(c1)( partition p0 values less than(10), partition p1 values less than(20), partition p2 values less than(30), partition p3 values less than (MAXVALUE) ); Query OK, 1 row affectedパーティションテーブル
t2_ins_overwrtを作成します。obclient> CREATE TABLE t2_ins_overwrt (c1 int primary key, c2 int) partition by range(c1)( partition p0 values less than(10), partition p1 values less than(20), partition p2 values less than(30), partition p3 values less than (MAXVALUE) ); Query OK, 1 row affectedそれぞれのテーブルに数件のデータを挿入します。
obclient> INSERT INTO t1_ins_overwrt values (1, 10), (12, 20), (23, 30), (34, 40), (45, 50); Query OK, 5 rows affected (0.018 sec) Records: 5 Duplicates: 0 Warnings: 0 obclient> INSERT INTO t2_ins_overwrt values (3, 60), (8, 80), (17, 170), (26, 260), (29, 290), (142, 1420); Query OK, 6 rows affected (0.015 sec) Records: 6 Duplicates: 0 Warnings: 0それぞれのテーブルからp3パーティションのデータをクエリします。
obclient> SELECT * FROM t1_ins_overwrt partition(p3); +------+------+ | c1 | c2 | +------+------+ | 34 | 40 | | 45 | 50 | +------+------+ 2 rows in set (0.006 sec) obclient> SELECT * FROM t2_ins_overwrt partition(p3); +------+------+ | c1 | c2 | +------+------+ | 142 | 1420 | +------+------+ 1 row in set (0.006 sec)次のSQLクエリを実行して
t1_ins_overwrtテーブルのp3パーティションのデータをt2_ins_overwrtテーブルのp3パーティションに挿入します。obclient> INSERT OVERWRITE t2_ins_overwrt partition(p3) select * from t1_ins_overwrt partition(p3); Query OK, 2 rows affected (1.354 sec) Records: 2 Duplicates: 0 Warnings: 0t2_ins_overwrtテーブルのp3パーティションをクエリしたところ、データがすでに上書きされていることが確認できました。obclient> SELECT * FROM t2_ins_overwrt partition(p3); +------+------+ | c1 | c2 | +------+------+ | 34 | 40 | | 45 | 50 | +------+------+ 2 rows in set (0.006 sec)
例3
パーティションテーブル
tbl1を作成します。obclient [test]> CREATE TABLE tbl1(col1 INT,col2 INT) PARTITION BY RANGE COLUMNS(col1) SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 ( PARTITION p0 VALUES LESS THAN(10), PARTITION p1 VALUES LESS THAN(20)); Query OK, 0 rows affectedtbl1テーブルに1件のデータを挿入します。obclient [test]> INSERT INTO tbl1 (col1, col2) VALUES (2, 3); INSERT INTO tbl1 (col1, col2) VALUES (15, 2);テーブル
tbl1のパーティションp0にデータが挿入されているかをクエリします。obclient [test]> SELECT * FROM tbl1 PARTITION (p0);クエリ結果は以下のとおりです:
+------+------+ | col1 | col2 | +------+------+ | 2 | 3 | +------+------+obclient [test]> SELECT * FROM tbl1 PARTITION (p1);クエリ結果は以下のとおりです:
+------+------+ | col1 | col2 | +------+------+ | 15 | 2 | +------+------+パーティションテーブル
tbl2を作成します。obclient [test]> CREATE TABLE tbl2(col1 INT,col2 INT) PARTITION BY RANGE COLUMNS(col1) SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 ( PARTITION p0 VALUES LESS THAN(10), PARTITION p1 VALUES LESS THAN(20)); Query OK, 0 rows affectedテーブル
tbl2にデータを挿入します。obclient [test]> INSERT INTO tbl2 (col1, col2) VALUES (0, 22); INSERT INTO tbl2 (col1, col2) VALUES (18, 6);テーブル
tbl2のp0とp1パーティションにデータが挿入されているかをクエリします。obclient [test]> SELECT * FROM tbl2 PARTITION (p0);クエリ結果は以下のとおりです:
+------+------+ | c1 | c2 | +------+------+ | 0 | 22 | +------+------+obclient [test]> SELECT * FROM tbl2 PARTITION (p1);クエリ結果は以下のとおりです:
+------+------+ | c1 | c2 | +------+------+ | 18 | 6 | +------+------+insert overwriteを使用して、テーブルtbl1のデータをテーブルtbl2の指定されたパーティションp1に上書き書き込みます。obclient [test]> insert overwrite tbl2 partition (p1) select * from tbl1 partition (p1);テーブル
tbl2のパーティションp1のデータが上書きされているか検証します。obclient [test]> SELECT * FROM tbl2 PARTITION (p1);クエリ結果は以下のとおりです:
+------+------+ | col1 | col2 | +------+------+ | 15 | 2 | +------+------+結果は、テーブル
tbl2のパーティションp1のデータが上書きされたことを示しています。
REPLACE INTOステートメントを使用してデータを挿入する
INSERT ステートメント以外にも、テーブルにデータレコードが存在しない場合、またはテーブルにデータレコードが存在するが、主キーまたは一意キーとの競合がない場合、REPLACE INTO ステートメントを INSERT ステートメントの代わりに使用してデータを挿入することができます。REPLACE INTO ステートメントの構文の詳細と説明については、REPLACEを参照してください。
例:
テーブル
t_replaceの作成後、REPLACE INTOステートメントを使用してデータを挿入します。obclient [test]> CREATE TABLE t_replace( id int NOT NULL PRIMARY KEY , name varchar(10) NOT NULL , value int ,gmt_create timestamp NOT NULL DEFAULT current_timestamp ); Query OK, 0 rows affected obclient [test]> REPLACE INTO t_replace VALUES(1,'CN',2001, current_timestamp ()); Query OK, 1 row affected obclient [test]> SELECT * FROM t_replace; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 2001 | 2022-11-23 09:52:44 | +----+------+-------+---------------------+ 1 row in setデータレコードがあるテーブル
t_replaceに、REPLACE INTOステートメントを使用してデータを挿入します。obclient [test]> SELECT * FROM t_replace; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 2001 | 2022-03-22 16:13:55 | +----+------+-------+---------------------+ 1 row in set obclient [test]> REPLACE INTO t_replace values(2,'US',2002, current_timestamp ()); Query OK, 1 row affected obclient [test]> SELECT * FROM t_replace; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 2001 | 2022-11-23 09:52:44 | | 2 | US | 2002 | 2022-11-23 09:53:05 | +----+------+-------+---------------------+ 2 rows in set