【実機解説】PythonでKeyence PLCのデータをSQL Serverに自動保存する方法|設備IoTの土台づくり
導入:結論から先に
PLCから取得したデータは、Pythonと無料のSQL Serverを使えば、データベースに自動で溜め続けることができます。
これまでの記事で、PythonでKeyence PLCのデバイス値を読み出す方法や、FANUCロボットの電流値・位置座標をPLCで常時取得する方法を解説してきました。値が「取れる」ようになると、次に必ずぶつかるのがこの疑問です。
「取った値を、どこに・どうやって溜めればいいのか?」
CSVファイルに書き出す方法もありますが、データが増えると管理しきれなくなり、あとから「グラフ化したい」「異常検知したい」と思っても加工が大変です。最初からデータベース(DB)に溜めておくのが、設備IoTの王道です。
この記事では、私が実際に構築した流れをそのまま、次の3点に絞って解説します。
- 無料で使えるSQL Server Expressの導入(お金はかかりません)
- 設備が増えても困らないテーブル設計(実務で効いた設計の勘所)
- コピペで動くPythonコード(1行ずつコメント付き)
専門用語はできるだけ補足しながら進めます。データベースが初めての方でも、上から順にやれば動くところまで書きます。
全体構成:今回作るのはどこか
設備IoTの全体像の中で、今回作るのは「Python → SQL Server」の部分です。
PLC(電流値・座標などの値) │ ← 読み出し:前回までの記事で解説済み ▼ Python(値を受け取って整形) │ ← ★今回はここを作る ▼ SQL Server(データベースに蓄積) │ ▼ グラフで見える化/異常検知(次のステップ)
PLCからの読み出し部分は別記事で解説済みなので、この記事では「受け取った値をデータベースに保存する」部分に集中します。そのため、動作確認ではPLCの値を模擬した数値を使います(読み出しと組み合わせれば、そのまま実機構成になります)。
この記事で使う環境
| 役割 | ソフト | 費用 |
|---|---|---|
| データベース本体 | SQL Server 2022 Express | 無料 |
| DB管理ツール | SSMS 22(SQL Server Management Studio) | 無料 |
| プログラム | Python 3(今回は3.12で確認) | 無料 |
| PythonからDBへ接続する部品 | pyodbc+ODBC Driver 18 | 無料 |
SQL Serverを選ぶ理由:製造業の現場システムでは、Windowsとの相性が良いSQL Serverが事実上の標準です。無料のExpress版でも、設備数台ぶんのデータ収集には十分すぎる性能があります。
準備①:SQL Server 2022 Express を入れる(無料)
Microsoft公式ページから、無料のExpress版をダウンロードします。
👉 Microsoft公式:SQL Server 2022 Express ダウンロードページ
- ページの「ダウンロード」から
SQL2022-SSEI-Expr.exe(約4MB)を入手して実行 - 最初の選択画面で「基本(Basic)」を選ぶ(今回はこれで十分です)
- あとは同意して進めるだけ。本体をダウンロードしながらインストールされます
インストールが完了すると、接続に必要な情報が表示されます。この画面の「インスタンス名」(標準では SQLEXPRESS)を覚えておいてください。あとでPythonからの接続に使います。

準備②:SSMS(管理ツール)を入れる
次に、データベースの中身を見たりテーブルを作ったりする管理ツール「SSMS」を入れます。こちらも無料です。
👉 Microsoft公式:SSMSのインストールページ(「Download the SQL Server Management Studio 22 installer」からダウンロード)
vs_SSMS.exeを実行- 「Visual Studio Installer」という画面が開くが、チェックは何も追加せずそのまま「インストール」でOK(コア機能だけで十分)
準備③:SSMSでSQL Serverに接続する
SSMSを起動すると接続画面が出ます。次のように入力します。
- サーバー名:
localhost\SQLEXPRESS(自分のPCの中のSQL Server、という意味) - 認証:Windows認証(パスワード入力は不要)
- 「サーバー証明書を信頼する」に必ずチェック ← ここが最初のつまずきポイント!

なぜチェックが必要?:最近のSSMSは通信の暗号化が標準でオンになっています。自分のPC内の接続では簡易的な証明書が使われるため、チェックを入れないと「証明書チェーンは信頼されていない機関によって発行されました」というエラーで接続できません。ローカル接続なので信頼して問題ありません。
【設計の勘所】設備が増えても困らないテーブル設計
ここがこの記事でいちばん伝えたいことです。コードよりも大事です。
データを溜めるテーブル(表)を作るとき、初心者がやりがちな設計がこれです。
- ❌ 設備が増えるたびに、新しいテーブルを作る(robot1_log、robot2_log…)
- ❌ 設備が増えるたびに、列を増やす(robot1_x、robot2_x…)
これをやると、設備が1台増えるたびにテーブルもプログラムも作り直しになり、運用が破綻します。
私が実務のデータ収集システムで採用して効果があったのは、次の形です。
- ✅ 「設備リスト」のテーブルを別に持ち、各設備にIDを振る
- ✅ データ収集テーブルには「どの設備の値か(設備ID)」を1列持たせるだけ
- ✅ 2つのテーブルを設備IDでリレーション(関連付け)する
| テーブル | 役割 | 主な列 |
|---|---|---|
| equipment(設備リスト) | 設備の台帳 | equipment_id(主キー)/equipment_name/line |
| robot_log(データ収集) | 値を溜める本体 | equipment_id(設備リストと紐づく外部キー)/recorded_at/pos_x・pos_y・pos_z/current_j1 |
2つのテーブルは equipment_id でリレーション(関連付け)されています。
この形にしておくと、設備が3台目、4台目と増えても「設備リストに1行追加するだけ」。データ収集テーブルもプログラムも一切変更不要です。逆に、最初にこの設計をサボると、後からの変更は本当に大変です。
データベースとテーブルを作る(コピペで完成)
SSMSの「新しいクエリ」を開き、次のSQLを貼り付けてF5(実行)してください。データベース作成からテーブル2つ、サンプル設備の登録まで一度に完了します。
-- ① データ収集用のデータベースを作成 IF DB_ID('plc_iot') IS NULL CREATE DATABASE plc_iot; GO USE plc_iot; GO -- ② 設備リスト(台帳):設備IDを主キーに持つ CREATE TABLE equipment ( equipment_id INT PRIMARY KEY, -- 設備ID(主キー) equipment_name NVARCHAR(50) NOT NULL, -- 設備名 line NVARCHAR(20) NULL -- ライン名 ); GO -- ③ データ収集(本体):設備IDで設備リストと紐づく CREATE TABLE robot_log ( id BIGINT IDENTITY(1,1) PRIMARY KEY, -- 連番(自動採番) equipment_id INT NOT NULL, -- どの設備の値か recorded_at DATETIME2(0) NOT NULL, -- 記録時刻 pos_x FLOAT NULL, -- 現在位置X pos_y FLOAT NULL, -- 現在位置Y pos_z FLOAT NULL, -- 現在位置Z current_j1 FLOAT NULL, -- J1軸の電流値 CONSTRAINT fk_robot_log_equipment -- 設備リストとのリレーション FOREIGN KEY (equipment_id) REFERENCES equipment(equipment_id) ); GO -- ④ 設備リストに設備を登録(増えたらここに足すだけ) INSERT INTO equipment (equipment_id, equipment_name, line) VALUES (1, N'FANUC R-30iB #1', N'A'), (2, N'FANUC R-30iB #2', N'A'); GO
「コマンドは正常に完了しました」と出れば成功です。左のツリーを更新すると、plc_iot の中に equipment と robot_log の2テーブルができています。

列の内容(pos_xやcurrent_j1)は例です。ご自身が集めたい値に合わせて増減してください。前回の記事のように、ロボットの座標・電流値をPLCに取得している場合は、そのデバイス値をそのまま入れる想定です。
Python側の準備:pyodbcを入れる
PythonからSQL Serverに接続するための部品「pyodbc」を入れます。コマンドプロンプトで1行です。
pip install pyodbc
接続には「ODBCドライバ」も必要ですが、SQL Serverを入れると「ODBC Driver 18 for SQL Server」が一緒に入っていることが多いです。次の1行で、自分のPCに入っているドライバを確認できます。
python -c "import pyodbc; print(pyodbc.drivers())"
表示された一覧に ODBC Driver 18 for SQL Server(または17)があればOKです。
Pythonで保存する(コピペで動くコード)
いよいよ本体です。値を読み取り、設備IDと一緒にSQL Serverへ保存するコードです。1行ずつコメントを付けています。
# -*- coding: utf-8 -*- import pyodbc # SQL Serverに接続するための部品 import random # 今回はPLCの代わりに模擬値を作る from datetime import datetime # 記録時刻を入れる # --- SQL Serverへの接続設定 --- CONN_STR = ( "DRIVER={ODBC Driver 18 for SQL Server};" # 使うODBCドライバ "SERVER=localhost\\SQLEXPRESS;" # サーバー名(\は2つ重ねる) "DATABASE=plc_iot;" # 使うデータベース "Trusted_Connection=yes;" # Windows認証(パスワード不要) "Encrypt=yes;TrustServerCertificate=yes;" # ローカルの証明書を信頼する ) def read_plc_values(): # 本来はPLCから読み出す部分(読み出し方法は別記事参照)。 # ここでは動作確認のため、それらしい模擬値を返す。 return { "pos_x": round(random.uniform(90, 110), 1), # 現在位置X "pos_y": round(random.uniform(-10, 10), 1), # 現在位置Y "pos_z": round(random.uniform(400, 420), 1), # 現在位置Z "current_j1": round(random.uniform(1.0, 5.0), 2), # J1軸電流値 } def save(equipment_id, values): conn = pyodbc.connect(CONN_STR) # DBに接続する cur = conn.cursor() # 命令を出す係を用意 cur.execute( # 1行ぶんをINSERT(保存) "INSERT INTO robot_log " "(equipment_id, recorded_at, pos_x, pos_y, pos_z, current_j1) " "VALUES (?, ?, ?, ?, ?, ?)", # ?の場所に下の値が順に入る equipment_id, datetime.now(), # 設備IDと現在時刻 values["pos_x"], values["pos_y"], # 位置X・Y values["pos_z"], values["current_j1"], # 位置Z・電流値 ) conn.commit() # 確定(忘れると保存されない!) conn.close() # 接続を閉じる # --- メイン:60秒ごとに設備1と設備2の値を保存し続ける --- import time # 待ち時間用 while True: # ずっと繰り返す for eq_id in (1, 2): # 設備リストにある設備ID分ループ save(eq_id, read_plc_values()) # 値を読んで保存 time.sleep(60) # 60秒待って次の記録へ
ポイント:設備が増えたら、SQL側は設備リストに1行足し、コードは
(1, 2)を(1, 2, 3)にするだけです(設備リストから自動で読む形にもできます)。テーブルは何も変えなくてよいのが、先ほどの設計の効果です。
動作確認:データが溜まっていく様子を見る
スクリプトを動かした状態で、SSMSで robot_log を右クリック →「上位1000行の選択」を実行すると、行がどんどん増えていくのが確認できます。

設備ID(equipment_id)ごとに値が振り分けられて記録されているのがわかります。これで「取る → 溜める」までの流れが完成しました。
つまずきポイント集(実際にハマった所)
今回の構築で実際に遭遇した・遭遇しやすいポイントです。
- ①「証明書チェーンは信頼されていない機関によって…」エラー
SSMSなら接続画面の「サーバー証明書を信頼する」にチェック。Pythonなら接続文字列にTrustServerCertificate=yes;を入れます。 - ② サーバー名の「\」はPythonでは2つ重ねる
localhost\SQLEXPRESSをPythonの文字列にそのまま書くと警告が出ます。"localhost\\SQLEXPRESS"のように2つ重ねてください。 - ③ commit() を忘れると保存されない
エラーも出ないのにデータが増えないときは、まずここを疑ってください。 - ④ 接続できないときはサービスを確認
Windowsの「サービス」でSQL Server (SQLEXPRESS)が「実行中」になっているか確認します。 - ⑤ ODBCドライバ名の不一致
接続文字列のドライバ名は、先ほどのpyodbc.drivers()で表示された名前と一致させてください。
【締め】「取る→溜める」の次は「活かす」
これで、PLCから取得した値をデータベースに溜め続ける土台ができました。
データベースに溜まったデータは、ここからが本領です。
- 稼働状況のグラフ化:時系列で並べれば、いつ・どれだけ動いたかが見える
- 電流値の監視:いつもと違う負荷の傾向を早期に察知
- 設備間の比較:設備IDで紐づけてあるので、同型設備の比較も簡単
取るのは前回まで、溜めるのが今回。次は「活かす」——可視化・異常検知です。このシリーズで、設備IoTの一気通貫の流れを引き続き解説していきます。
関連記事
- PythonでKeyence PLCのデバイスを読み出す方法(上位リンク通信)
- 【実機解説】Keyence PLCでFANUCロボットの電流値・位置座標を常時取得する方法(プロトコルスタジオ)
- FANUCロボット × Keyence PLC のEthernet/IP設定方法【実機解説】
お問い合わせ
「設備のデータを溜めて見える化したい」「PLCデータの収集システムを作りたい」
そんなご相談を承っています。PLC側の設定から、データベース設計・蓄積・活用の仕組みづくりまで一気通貫で対応できます。お気軽にお問い合わせください。

