[PR] 本記事にはプロモーションが含まれています。

【データベース編 第3回】データを入れる ― INSERT と NULL を、C の構造体の初期化と並べて

MySQL

前回は、練習用のデータベース sql_practice に、架空の検査値を記録する表 measurements を作りました。列は6つ(id、measured_on、item_name、value_text、value_num、unit)で、中身はまだ空っぽです。

今回は、この表にデータを入れます。使う命令は INSERT です。数値にできない「(-)」のような結果の入れ方と、必須の列を入れ忘れたときにどうなるかも試します。

また、中で bash を打ってしまった

今回の練習でも、第1回で書いた失敗をもう一度やってしまいました。MariaDB の中に入れたことに気づかず、入るためのコマンドを、中でもう一度打ったのです。

SQL
MariaDB [sql_practice]> mysql -u practice -p sql_practice -e "SELECT DATABASE();"
    -> ^C

    -> exit
    -> q
    -> ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'mysql -u practice -p sql_practice -e "SELECT DATABASE();"

exit
q' at line 1
MariaDB [sql_practice]>

Ctrl + C(^C)も exit も q も、「SQL の続き」として受け取られ、最後の ; でようやく1つの命令として終わりました。中身はでたらめなので ERROR 1064(書き方の誤り)になりますが、何も変わっていません。行頭が MariaDB [sql_practice]> に戻ったので、そのまま練習を続けました。

第1回で書いたとおり、行頭の表示で、今どこにいるかを確かめるのが大事だと、改めて感じました。

INSERT は「構造体に値を入れて、配列に足す」

C で、前回の構造体に値を入れて、配列の空いているところに足すと、次のようになります。

C
struct measurement m = {
    .measured_on = DATE(2026, 9, 1),
    .item_name   = "血糖",
    .value_text  = "98",
    .value_num   = FIXED(98.000),
    .unit        = "mg/dL",
};
records[count++] = m;   /* id は、足した順の通し番号 */

SQL では、これを INSERT の1行で頼みます。

C でやることSQL の INSERT
どの配列に足すかINSERT INTO measurements
どのメンバに入れるか(measured_on, item_name, …) と列の名前を並べる
入れる値VALUES (‘2026-09-01’, ‘血糖’, …) と、列と同じ順に並べる
通し番号 count++id は書かない。AUTO_INCREMENT で自動で振られる

(DATE() と FIXED() は、説明のための書き方です。前回の date_t、fixed_t と同じく、実際の C にはこの名前の型や関数はありません)

データを入れる

① 練習用のユーザーで入る

Bash
$ mysql -u practice -p sql_practice

パスワードを入れると、行頭が MariaDB [sql_practice]> に変わります。ここから先は、すべて MariaDB の中で打ちます。

② 1行だけ入れる

SQL
INSERT INTO measurements (measured_on, item_name, value_text, value_num, unit)
VALUES ('2026-09-01', '血糖', '98', 98, 'mg/dL');

結果の例:

Plaintext
Query OK, 1 row affected (0.005 sec)

1 row affected は「1行に影響した」、つまり1行入った、という意味です。

書き方の決まりは、次のとおりです。

  • INSERT INTO measurements:
    「measurements の表に入れる」という意味
  • (measured_on, item_name, value_text, value_num, unit):
    値を入れる列の名前。id は書かない(AUTO_INCREMENT で自動で振られる)
  • VALUES (…):
    入れる値。かっこの中の列と、同じ順番で並べる
  • ‘2026-09-01’、’血糖’、’98’:
    日付と文字は ‘ ‘(シングルクォート)で囲む。value_text は文字の列なので、数字でも ’98’ と囲む
  • 98:
    value_num は数値の列なので、囲まずにそのまま書く

③ まとめて何行も入れる

1回の INSERT で、何行もまとめて入れられます。VALUES のあとに、( ) の組を , で区切って並べます。

SQL
INSERT INTO measurements (measured_on, item_name, value_text, value_num, unit) VALUES
('2026-09-01', 'CRP',   '0.05',     0.05, 'mg/dL'),
('2026-09-01', '尿蛋白', '(-)',      NULL, NULL),
('2026-10-01', '血糖',   '104',      104,  'mg/dL'),
('2026-10-01', 'CRP',   '0.03未満', 0.03, 'mg/dL'),
('2026-10-01', '尿蛋白', '(+-)',     NULL, NULL);

結果の例:

Plaintext
Query OK, 5 rows affected
Records: 5  Duplicates: 0  Warnings: 0
  • Records: 5:
    入れようとした行の数
  • Duplicates: 0:
    重複して入らなかった行の数
  • Warnings: 0:
    値を切り詰めたり、型を合わせたりして、注意が出た行の数。0 なら、書いたとおりに入っている

④ 入ったデータを見る

SQL
SELECT * FROM measurements;

結果の例:

Plaintext
+----+-------------+-----------+------------+-----------+-------+
| id | measured_on | item_name | value_text | value_num | unit  |
+----+-------------+-----------+------------+-----------+-------+
|  1 | 2026-09-01  | 血糖      | 98         |    98.000 | mg/dL |
|  2 | 2026-09-01  | CRP       | 0.05       |     0.050 | mg/dL |
|  3 | 2026-09-01  | 尿蛋白    | (-)        |      NULL | NULL  |
|  4 | 2026-10-01  | 血糖      | 104        |   104.000 | mg/dL |
|  5 | 2026-10-01  | CRP       | 0.03未満   |     0.030 | mg/dL |
|  6 | 2026-10-01  | 尿蛋白    | (+-)       |      NULL | NULL  |
+----+-------------+-----------+------------+-----------+-------+
6 rows in set (0.000 sec)

SELECT * は「全部の列を見る」という意味です。くわしくは次回あつかいます。

id は 1 から 6 まで、入れた順に自動で振られています。value_num は、前回 DECIMAL(10,3) にしたので、98 も 98.000 と、小数点以下3桁で表示されます。

INSERT の命令の1行が、表 measurements の新しい行(id 6)になり、id は AUTO_INCREMENT で自動で振られ、value_num と unit には NULL が入ることを示した図

数値にできない結果は、NULL で入れる

尿蛋白の「(-)」や「(+-)」は、数値にできません。そこで、value_text には用紙のとおり ‘(-)’ を入れ、value_num と unit には NULL を入れています。

書き方意味C でいうと
NULL値がない(空)NULL を入れたポインタ
‘NULL’「N・U・L・L」という4文字の文字列“NULL” という文字列

NULL は ‘ ‘ で囲みません。囲むと、ただの文字になってしまいます。表示でも、NULL は「値がない」という意味で NULL と出ます。

「0.03未満」はどう入れたか

CRP の「0.03未満」は、value_text には ‘0.03未満’ と用紙のとおりに入れ、value_num には 0.03 を入れました。グラフに点を打つための数値としては、境目の 0.03 を使う、という決め方です。

ただし、value_num の 0.030 だけを見ると、「ちょうど 0.03」なのか「0.03未満」なのかは分かりません。前回、結果を value_text と value_num の2つの列で持つことにしたのは、こういう値の元の意味を、value_text に残しておくためです。

必須の列を入れ忘れると

前回、value_text は NOT NULL(必ず値を入れる)にしました。わざと value_text を入れずに INSERT してみます。

SQL
INSERT INTO measurements (measured_on, item_name) VALUES ('2026-10-01', 'テスト');
SELECT COUNT(*) FROM measurements;

結果の例:

Plaintext
ERROR 1364 (HY000): Field 'value_text' doesn't have a default value
+----------+
| COUNT(*) |
+----------+
|        6 |
+----------+
1 row in set (0.000 sec)

エラーは「value_text に初期値(default value)がない」という意味です。必ず値を入れる列なのに、値も初期値もないので、入れられなかったということです。

SELECT COUNT(*) は、表の行の数を数える命令です(第5回でくわしくあつかいます)。6 のままなので、エラーになった行は、途中まで入ったりせずに、まったく入っていません。

組み込みでいえば、必須の項目が欠けたコマンドフレームを、受け側がはじいて、メモリに何も書かなかった、という動きです。中途半端なデータが残らないので安心です。

やり直したいときは

練習で入れたデータを全部消して、最初からやり直したいときは、次の命令で表を空にできます。

SQL
TRUNCATE TABLE measurements;
  • TRUNCATE TABLE 表の名前:
    表の形(列の定義)は残したまま、中の行を全部消す。id の番号も、次は 1 から振り直しになる

私も、この記事の練習の途中で入れるデータを決め直したので、一度 TRUNCATE で空にしてから、上の ②・③ を入れ直しています。ただし、元に戻すことはできないので、練習用のデータベース以外では使わないようにしています。

まとめと次回予告

この回で覚えたことC でいうと
INSERT INTO 表 (列…) VALUES (値…) で1行入れる構造体に値を入れて、配列に足す
VALUES のあとに ( ) を , で並べると、まとめて入れられる配列にまとめてコピーする
文字と日付は ‘ ‘ で囲み、数値はそのまま書く文字列リテラルと数値リテラル
id は書かずに、自動で振らせる通し番号のカウンタ count++
値がないところは NULL(囲まない)NULL を入れたポインタ
必須の列が欠けると、行ごと入らない欠けたフレームは、受け側ではじく

表に6行のデータが入りました。次回は、このデータを「見る・絞り込む・並べる」です。SELECT で必要な列だけを見たり、WHERE で日付や項目を絞り込んだり、ORDER BY で並べ替えたりします。
→ データベース編 第4回:見る・絞り込む・並べる

この記事は、シリーズ「組み込みエンジニアの Web 開発入門」の1本です。ほかの回は、シリーズの目次からどうぞ。

ほかの開発・プログラミングの記事は、開発・プログラミングメモの目次から、テーマ別に探せます。

このブログは、にほんブログ村と人気ブログランキングに参加しています。記事が役に立ったら、下のランキングのバナーのどれかを押して応援してもらえると励みになります。

ブログランキング・にほんブログ村へにほんブログ村

サーバー構築・運用ランキング プログラムランキング

MySQL
watasoftdevをフォローする

コメント