C言語+MySQL入門|学習用の接続ユーザーを作る

C言語+MySQL入門|学習用の接続ユーザーを作る

これまでの記事では、管理作業用のアカウントでデータベースやテーブルを作成し、商品の登録・変更・削除を行いました。

今回は、第4章のCプログラムからMySQLへ接続するために、学習用の専用ユーザーを作成します。

ユーザーを作るだけでなく、在庫管理アプリで使う2つのテーブルに対して、データを読み書きする権限も付けましょう。

この記事では、次の内容を学びます。

  • 管理作業用とアプリ用のアカウントを使い分ける。
  • MySQLのユーザー名と接続元の関係を理解する。
  • CREATE USERで専用ユーザーを作成する。
  • GRANTで必要な操作を許可する。
  • 作成したユーザーで接続できることを確認する。

権限の確認は次の記事で、権限設計の詳しい考え方は第9章で扱います。今回は、Cプログラムから接続するための準備を整えていきましょう。

アプリ用の接続ユーザーを用意しよう

これまで使用してきたrootは、MySQLの管理作業に使うアカウントです。

データベースの作成やユーザーの管理など、広い範囲の操作を行えます。一方、在庫管理アプリが日常的に行うのは、商品の表示や登録、在庫情報の更新などです。

そこで、役割に合わせてアカウントを使い分けます。

アカウント主な用途
rootデータベースやテーブルの作成、ユーザーと権限の管理
inventory_userCプログラムから商品や在庫履歴のデータを操作する

今回作成するユーザー名はinventory_userです。

Cプログラムでは、このユーザーを使って接続する方針にします。アプリ用の接続情報と管理作業用の接続情報を分けることで、プログラムに許可する操作を明確にできます。

なお、ここで作成するのはMySQLのアカウントです。Windowsへのサインインに使うユーザーや、在庫管理アプリの利用者情報を作成するわけではありません。

図1:管理作業用とアプリ用のアカウントを使い分ける

この図から分かること

データベースを管理する作業と、アプリからデータを読み書きする作業では、必要な操作が異なります。

今回用意するinventory_userは、在庫管理アプリのデータ操作に使う専用ユーザーです。

今回の接続情報を決めよう

学習用ユーザーは、次の内容で作成します。

項目今回の設定
ユーザー名inventory_user
接続を許可する接続元127.0.0.1
パスワードの例InventoryPass_2026
接続先のMySQL Server127.0.0.1
ポート番号3306
使用するデータベースinventory_db
操作対象のテーブルproducts、stock_history

InventoryPass_2026は、教材内で使うパスワードの例です。公開サーバーや実際の業務では、教材に掲載されたパスワードをそのまま使用せず、別のものを設定してください。

学習環境で別のパスワードを使う場合は、以降の接続操作でも、そのパスワードに読み替えます。

MySQLのアカウントはユーザー名と接続元の組み合わせ

MySQLでは、アカウントをユーザー名と接続元の組み合わせで区別します。

今回作成するアカウントは、説明上では次のように表せます。

inventory_user@127.0.0.1
部分意味
inventory_userユーザー名
@ユーザー名と接続元を区切る記号
127.0.0.1接続元を表すホスト情報

127.0.0.1は、自分自身のコンピューターを指すループバックアドレスです。今回は、MySQL ServerとCプログラムを同じWindows PCで動かすため、この接続元を使います。

ここで、2つの127.0.0.1の役割を区別しておきましょう。

  • 接続コマンドで指定する127.0.0.1は、接続先のサーバーを表す。
  • MySQLアカウントの接続元に指定する127.0.0.1は、そのアカウントを使って接続できるクライアントの場所を表す。

今回は同じPC内で接続するので、両方に同じアドレスが登場します。

接続方法を127.0.0.1のTCP接続にそろえる

この記事では、MySQLクライアントからも、今後のCプログラムからも、127.0.0.1を指定したTCP接続を使います。

localhostと127.0.0.1は、アカウント定義の接続元としては別の指定です。名前を置き換えれば必ず同じアカウントとして扱われる、と考えないようにしましょう。

接続先と接続方法をそろえておくと、設定と実際の接続を対応させやすくなります。

ユーザーの作成と権限の付与は別の操作

MySQLでは、アカウントを作成する操作と、データを操作する権限を付ける操作を分けて行います。

命令役割
CREATE USERアカウントを作成し、認証に使う情報を設定する
GRANT作成したアカウントに操作権限を付ける

CREATE USERでユーザーを作成しただけでは、productsなどのデータを操作する権限は付いていません。必要な権限をGRANTで追加します。dev.mysql.com

今回許可するのは、これまで学んだ4つのデータ操作です。

権限許可する操作
SELECTデータを取得する
INSERT新しい行を追加する
UPDATE保存済みの行を更新する
DELETE行を削除する

これらを、inventory_dbのproductsとstock_historyに付与します。

テーブル作成やユーザー作成などは、引き続き管理作業用のアカウントで行います。

管理作業用のアカウントでユーザーを作成しよう

ここからのCREATE USERとGRANTは、rootなど、アカウント管理と権限付与ができるユーザーで実行します。

前の記事からrootで接続したままであれば、その接続を使えます。接続していない場合は、3.2で学んだ手順で管理作業用のアカウントに接続してください。

以下が、今回使用するSQLの全体です。

Cプログラム用の接続ユーザーと操作権限を用意するSQL

ファイル名: create_inventory_user.sql

CREATE USER 'inventory_user'@'127.0.0.1'
    IDENTIFIED BY 'InventoryPass_2026';

GRANT SELECT, INSERT, UPDATE, DELETE
    ON inventory_db.products
    TO 'inventory_user'@'127.0.0.1';

GRANT SELECT, INSERT, UPDATE, DELETE
    ON inventory_db.stock_history
    TO 'inventory_user'@'127.0.0.1';
実行結果の例
Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

処理時間は環境によって異なります。3つの命令が、それぞれ正常に実行されたことを確認しましょう。

SQL内では、ユーザー名と接続元をそれぞれ引用符で囲み、その間に@を書いています。パスワードも文字列として指定するため、引用符が必要です。

なお、このSQLではUSE inventory_dbを実行する必要はありません。アカウントはMySQL Serverに作成され、操作権限の対象はinventory_db.productsのようにデータベース名付きで指定しているためです。

SQLファイルとして保存する場合は、パスワードが含まれることにも注意してください。そのまま公開したり、共有リポジトリへ登録したりしないようにします。

CREATE USERの指定を読み解こう

最初の命令では、ユーザー名、接続元、パスワードを設定しています。

SQLの部分意味
CREATE USER新しいMySQLアカウントを作成する
inventory_user作成するユーザー名
127.0.0.1アカウントの接続元
IDENTIFIED BYパスワードを指定する
InventoryPass_2026今回使用するパスワードの例

MySQL 8.4の標準設定では、認証方式としてcaching_sha2_passwordが使われます。今回のようにIDENTIFIED BYで作成した場合も、標準設定ではこの方式になります。

認証方式は、接続時にパスワードなどを使って本人確認を行うための仕組みです。この記事では、MySQL 8.4の標準設定を使って進めます。

GRANTで操作できる範囲を指定しよう

続く2つのGRANTでは、productsとstock_historyに対して、それぞれ操作権限を付けています。

SQLの部分意味
GRANT SELECT, INSERT, UPDATE, DELETE許可する4つの操作
ON inventory_db.productsproductsを対象にする
ON inventory_db.stock_historystock_historyを対象にする
TO権限を付けるアカウントを指定する

今回の指定は、テーブル単位の権限付与です。後から別のテーブルを追加した場合、そのテーブルの操作権限が自動的に付くわけではありません。

また、DELETE権限を付けても、外部キー制約が無効になることはありません。履歴から参照されている商品は、これまで設定したRESTRICTによって削除が拒否されます。

権限は操作を行ってよいかを決め、制約は保存するデータや参照関係のルールを守ります。

FLUSH PRIVILEGESは追加で実行しなくてよい

今回のようにCREATE USERやGRANTを使って設定した場合、追加のFLUSH PRIVILEGESは必要ありません。MySQL Serverの再起動も不要です。

この後、新しく作成したユーザーで接続して確認できます。

図2:ユーザー作成と権限付与を分けて考える

イラスト作成用プロンプト

この図から分かること

CREATE USERは、接続に使うアカウントを用意する操作です。

GRANTは、そのアカウントがどのテーブルで何をできるかを設定する操作です。両方を行うことで、アプリからデータを扱う準備が整います。

管理用の接続で作成結果を確認しよう

rootで接続している間に、作成したアカウントの情報を確認します。

SELECT User, Host, plugin
FROM mysql.user
WHERE User = 'inventory_user'
  AND Host = '127.0.0.1';
実行結果の例
+----------------+-----------+-----------------------+
| User           | Host      | plugin                |
+----------------+-----------+-----------------------+
| inventory_user | 127.0.0.1 | caching_sha2_password |
+----------------+-----------+-----------------------+
1 row in set (0.00 sec)

mysql.userは、MySQLがアカウント情報を管理しているシステムテーブルです。

今回は、ユーザー名、接続元、認証方式だけを参照しています。パスワード情報を表示する必要はありません。

また、アカウント設定を変更するときも、このテーブルを直接UPDATEするのではなく、CREATE USERやALTER USERなどの専用の命令を使います。

この確認は管理作業用のアカウントで行うものです。今回のinventory_userには、mysql.userを参照する権限は付けていません。

作成したユーザーで接続し直そう

アカウントを作成できたら、実際にinventory_userで接続してみましょう。

現在のMySQLクライアントを終了します。

exit
実行結果の例
Bye

ここからのコマンドは、mysql>ではなく、Windowsのコマンドプロンプトで実行します。

MySQLクライアントのあるフォルダーへ移動します。

cd /d "C:\Program Files\MySQL\MySQL Server 8.4\bin"

インストール先を変更している場合は、実際の場所に読み替えてください。

パスワードを後から入力して接続する

mysql --protocol=TCP -h 127.0.0.1 -P 3306 -u inventory_user -p
実行結果の例
Enter password:

ここで、作成時に設定したInventoryPass_2026を入力してEnterキーを押します。

入力したパスワードは、通常、画面には表示されません。

接続に成功すると案内文が表示され、その後に次のプロンプトが現れます。

mysql>

コマンドの指定を確認しておきましょう。

指定意味
mysqlMySQLクライアントを起動する
--protocol=TCPTCP接続を使う
-h 127.0.0.1接続先のサーバーを指定する
-P 3306ポート番号を指定する
-u inventory_userユーザー名を指定する
-pパスワードを後から入力する

-Pと-pは、大文字と小文字で意味が異なります。-Pはポート番号、-pはパスワードの指定です。

また、TCP接続を明示することで、今回決めた接続方法にそろえています。

パスワードをコマンドに直接指定する場合

学習環境で、パスワードをコマンドに直接書く場合は、次のようになります。

mysql --protocol=TCP -h 127.0.0.1 -P 3306 -u inventory_user -pInventoryPass_2026

-pとパスワードの間には、空白を入れません。

この方法では、パスワードが画面やコマンド履歴などに残る可能性があり、MySQLクライアントから警告が表示されることもあります。普段の操作では、先ほどの-pだけを指定する方法を使うとよいでしょう。

この2つは、同じアカウントへ接続するための別の入力方法です。すでに接続できている場合は、もう一方も続けて実行する必要はありません。

接続に使われたアカウントを確認しよう

inventory_userで接続したら、次のSQLを実行します。

SELECT CURRENT_USER() AS authenticated_account;
実行結果の例
+--------------------------+
| authenticated_account    |
+--------------------------+
| inventory_user@127.0.0.1 |
+--------------------------+
1 row in set (0.00 sec)

CURRENT_USER()は、MySQLが認証に使用したアカウントを返します。権限の判定に使われるアカウントを確認するときに役立ちます。

rootではなく、inventory_user@127.0.0.1と表示されていることを確認してください。

続けて、使用するデータベースを選択します。

USE inventory_db;
実行結果の例
Database changed

現在のデータベースも確認しておきましょう。

SELECT DATABASE() AS current_database;
実行結果の例
mysql> SELECT DATABASE() AS current_database;
+------------------+
| current_database |
+------------------+
| inventory_db     |
+------------------+
1 row in set (0.00 sec)

これで、学習用ユーザーとして接続し、inventory_dbを選択できました。

商品の取得や、付与された権限の詳しい確認は、次の記事で行います。

図3:Cプログラムと同じ接続情報でログインを確認する

この図から分かること

MySQLクライアントでも、今後作成するCプログラムでも、接続先、ポート番号、ユーザー名、パスワードが必要です。

先にMySQLクライアントで接続できることを確認しておくと、第4章で接続に失敗した場合に、アカウント設定とCプログラムの処理を分けて調べやすくなります。

ユーザー作成や接続でつまずいたときは

状況確認すること
CREATE USERが失敗する管理作業用のアカウントで実行しているか確認する
同じアカウントがすでに存在するユーザー名と接続元の組み合わせを確認する
パスワードの要件に違反すると表示される環境に設定された長さや文字種などの要件を満たすパスワードにする
GRANTが失敗するアカウント作成が成功しているか、対象テーブル名と実行ユーザーの権限を確認する
Access deniedと表示されるユーザー名、パスワード、接続元の設定を確認する
MySQL Serverへ接続できないMySQL84の起動状態と、接続先・ポート番号を確認する
接続はできるがデータ操作が拒否されるGRANTが成功しているか、操作対象と付与した権限を確認する

すでに存在するユーザーをすぐに作り直さない

CREATE USERを同じアカウントに対して再実行すると、通常はエラーになります。

その場合は、まず管理用の接続で既存の設定を確認しましょう。学習をやり直したいという理由だけで、すぐにDROP USERを実行する必要はありません。

また、CREATE USERにIF NOT EXISTSを付けても、既存アカウントのパスワードが今回の値に変更されるわけではありません。既存の設定を確認したうえで扱うことが大切です。

接続できることと、データを操作できることは別

ユーザー名とパスワードが正しくても、必要な権限がなければデータ操作はできません。

接続に成功することは認証の確認であり、SELECTやUPDATEを実行できることは権限の確認です。

この違いを意識すると、エラーメッセージから確認すべき場所を判断しやすくなります。

次は接続ユーザーの権限を確認しよう

次の記事では、inventory_userに付与した権限を表示し、productsやstock_historyを操作できることを確認します。

今回作成した専用ユーザーで接続した状態から、Cプログラムが利用するデータベース操作の準備を、もう一歩進めていきましょう。

Follow me!