Python×SQL完全ガイド:基礎から上級テクニック+エラー解決法
![]() |
20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード |
| |
週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ |
| |
10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks |
PythonとSQLの組み合わせは、データベース操作において最も強力で実用的なスキルの一つです。SQLiteからMySQL、PostgreSQLまで、様々なデータベースとPythonを連携させることで、効率的なデータ処理と分析が可能になります。本記事では、PythonでのSQL操作の基礎から高度なテクニック、よくあるエラーと解決方法まで、実践的なサンプルコードとともに詳しく解説します。
目次
Python×SQLの基本概念
SQLとは何か
SQL(Structured Query Language)は、リレーショナルデータベースを操作するための標準的な言語です。PythonからSQLを実行することで、データの追加、取得、更新、削除(CRUD操作)を効率的に行えます。
import sqlite3
# 基本的なデータベース操作
conn = sqlite3.connect('sample.db')
cursor = conn.cursor()
# テーブル作成
cursor.execute('CREATE TABLE users (id INTEGER, name TEXT, age INTEGER)')
# データ挿入
cursor.execute("INSERT INTO users VALUES (1, '田中', 25)")
conn.commit()
conn.close()
Pythonで使用する主要なライブラリ
# SQLite(標準ライブラリ)
import sqlite3
# MySQL
import mysql.connector
# PostgreSQL
import psycopg2
# SQLAlchemy(ORM)
from sqlalchemy import create_engine
# pandas(データ分析)
import pandas as pd
基礎レベル:SQLiteを使った基本操作
データベース接続とテーブル作成
def create_database():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS employees (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
department TEXT,
salary INTEGER
)
''')
conn.commit()
conn.close()
基本的なCRUD操作
class EmployeeDB:
def __init__(self):
self.conn = sqlite3.connect('company.db')
self.cursor = self.conn.cursor()
def add_employee(self, name, department, salary):
self.cursor.execute(
"INSERT INTO employees (name, department, salary) VALUES (?, ?, ?)",
(name, department, salary)
)
self.conn.commit()
def get_employee(self, employee_id):
self.cursor.execute("SELECT * FROM employees WHERE id = ?", (employee_id,))
return self.cursor.fetchone()
def update_salary(self, employee_id, new_salary):
self.cursor.execute(
"UPDATE employees SET salary = ? WHERE id = ?",
(new_salary, employee_id)
)
self.conn.commit()
def delete_employee(self, employee_id):
self.cursor.execute("DELETE FROM employees WHERE id = ?", (employee_id,))
self.conn.commit()
データの検索とフィルタリング
def search_employees():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# 条件付き検索
cursor.execute("SELECT * FROM employees WHERE department = ?", ("開発部",))
dev_employees = cursor.fetchall()
# 給与範囲での検索
cursor.execute(
"SELECT name, salary FROM employees WHERE salary BETWEEN ? AND ?",
(400000, 600000)
)
salary_range = cursor.fetchall()
# 並び替え
cursor.execute("SELECT * FROM employees ORDER BY salary DESC")
sorted_employees = cursor.fetchall()
conn.close()
return dev_employees, salary_range, sorted_employees
中級レベル:複雑なSQL操作
JOINを使ったテーブル結合
def setup_related_tables():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# 部署テーブル
cursor.execute('''
CREATE TABLE IF NOT EXISTS departments (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
manager_id INTEGER
)
''')
# INNER JOIN例
cursor.execute('''
SELECT e.name, e.salary, d.name as department_name
FROM employees e
INNER JOIN departments d ON e.department = d.name
''')
conn.commit()
conn.close()
集約関数とグループ化
def aggregation_queries():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# 基本統計
cursor.execute('''
SELECT COUNT(*), AVG(salary), MAX(salary), MIN(salary)
FROM employees
''')
stats = cursor.fetchone()
# 部署別集計
cursor.execute('''
SELECT department, AVG(salary), COUNT(*)
FROM employees
GROUP BY department
''')
dept_stats = cursor.fetchall()
# サブクエリ
cursor.execute('''
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
''')
above_avg = cursor.fetchall()
conn.close()
return stats, dept_stats, above_avg
トランザクション処理
def transaction_example():
conn = sqlite3.connect('company.db')
try:
conn.execute("BEGIN")
conn.execute("UPDATE employees SET salary = salary * 1.1 WHERE department = '開発部'")
conn.execute("INSERT INTO employees (name, department, salary) VALUES (?, ?, ?)",
("新入社員", "開発部", 400000))
conn.commit()
print("トランザクション完了")
except Exception as e:
conn.rollback()
print(f"ロールバック: {e}")
finally:
conn.close()
上級レベル:高度なデータベース操作
SQLAlchemyを使ったORM
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class Employee(Base):
__tablename__ = 'employees_orm'
id = Column(Integer, primary_key=True)
name = Column(String(100))
department = Column(String(50))
salary = Column(Integer)
# データベース接続
engine = create_engine('sqlite:///orm_example.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
def orm_operations():
session = Session()
# データ追加
new_employee = Employee(name="山田", department="営業部", salary=480000)
session.add(new_employee)
# データ検索
employees = session.query(Employee).filter(Employee.department == "営業部").all()
session.commit()
session.close()
pandasとの連携
import pandas as pd
def pandas_integration():
conn = sqlite3.connect('company.db')
# SQLクエリ結果をDataFrameに読み込み
df = pd.read_sql_query("""
SELECT department, AVG(salary) as avg_salary, COUNT(*) as count
FROM employees
GROUP BY department
""", conn)
# DataFrameをSQLテーブルに保存
sample_data = pd.DataFrame({
'product': ['商品A', '商品B', '商品C'],
'price': [1000, 1500, 2000]
})
sample_data.to_sql('products', conn, if_exists='replace', index=False)
conn.close()
return df
動的SQLクエリの構築
def build_dynamic_query(filters=None, sort_by=None):
base_query = "SELECT * FROM employees WHERE 1=1"
params = []
if filters:
if 'department' in filters:
base_query += " AND department = ?"
params.append(filters['department'])
if 'min_salary' in filters:
base_query += " AND salary >= ?"
params.append(filters['min_salary'])
if sort_by:
base_query += f" ORDER BY {sort_by}"
return base_query, params
def flexible_search(department=None, min_salary=None):
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
filters = {}
if department: filters['department'] = department
if min_salary: filters['min_salary'] = min_salary
query, params = build_dynamic_query(filters, "salary DESC")
cursor.execute(query, params)
results = cursor.fetchall()
conn.close()
return results
SQL関連のエラーと解決方法
sqlite3.OperationalError:SQL構文エラー
def handle_sql_errors():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
try:
# 間違ったテーブル名
cursor.execute("SELECT * FROM employee") # employeesが正しい
except sqlite3.OperationalError as e:
print(f"SQLエラー: {e}")
# SQLインジェクション対策
def safe_query(user_input):
# 危険:cursor.execute(f"SELECT * FROM employees WHERE name = '{user_input}'")
# 安全:パラメータ化クエリ
cursor.execute("SELECT * FROM employees WHERE name = ?", (user_input,))
return cursor.fetchall()
conn.close()
sqlite3.IntegrityError:制約違反エラー
def handle_integrity_errors():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# UNIQUE制約テーブル
cursor.execute('''
CREATE TABLE IF NOT EXISTS unique_employees (
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL
)
''')
try:
cursor.execute("INSERT INTO unique_employees VALUES (?, ?)",
("[email protected]", "テストユーザー"))
# 重複エラー
cursor.execute("INSERT INTO unique_employees VALUES (?, ?)",
("[email protected]", "別のユーザー"))
except sqlite3.IntegrityError as e:
print(f"制約違反: {e}")
# UPSERT操作
cursor.execute("INSERT OR REPLACE INTO unique_employees VALUES (?, ?)",
("[email protected]", "更新されたユーザー"))
conn.commit()
conn.close()
接続エラーとリソース管理
class DatabaseManager:
def __init__(self, db_path):
self.db_path = db_path
self.conn = None
def __enter__(self):
self.conn = sqlite3.connect(self.db_path)
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if self.conn:
if exc_type is None:
self.conn.commit()
else:
self.conn.rollback()
self.conn.close()
# 使用例
def safe_operation():
with DatabaseManager('company.db') as conn:
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM employees")
count = cursor.fetchone()[0]
print(f"従業員数: {count}")
パフォーマンス最適化
インデックスの活用
def create_indexes():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# 単一カラムインデックス
cursor.execute("CREATE INDEX IF NOT EXISTS idx_department ON employees(department)")
# 複合インデックス
cursor.execute("CREATE INDEX IF NOT EXISTS idx_dept_salary ON employees(department, salary)")
conn.commit()
conn.close()
バッチ処理
def batch_operations():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
# 効率的なバッチ挿入
batch_data = [(f"社員{i}", "営業部", 400000) for i in range(1000)]
cursor.executemany(
"INSERT INTO employees (name, department, salary) VALUES (?, ?, ?)",
batch_data
)
conn.commit()
conn.close()
実践的なSQL活用パターン
ログ分析システム
def create_log_analysis():
conn = sqlite3.connect('logs.db')
cursor = conn.cursor()
# ログテーブル作成
cursor.execute('''
CREATE TABLE IF NOT EXISTS access_logs (
timestamp DATETIME,
ip_address TEXT,
url TEXT,
status_code INTEGER
)
''')
# エラー率分析
cursor.execute('''
SELECT url, COUNT(*) as total,
SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) as errors,
ROUND(SUM(CASE WHEN status_code >= 400 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as error_rate
FROM access_logs
GROUP BY url
ORDER BY error_rate DESC
''')
conn.commit()
conn.close()
売上レポート
def sales_reporting():
conn = sqlite3.connect('sales.db')
cursor = conn.cursor()
# 月次売上レポート
cursor.execute('''
SELECT strftime('%Y-%m', sale_date) as month,
SUM(quantity * unit_price) as total_sales
FROM sales
GROUP BY strftime('%Y-%m', sale_date)
ORDER BY month DESC
''')
monthly_sales = cursor.fetchall()
# 商品別売上ランキング
cursor.execute('''
SELECT product_name, SUM(quantity * unit_price) as revenue
FROM sales
GROUP BY product_name
ORDER BY revenue DESC
LIMIT 10
''')
top_products = cursor.fetchall()
conn.close()
return monthly_sales, top_products
在庫管理システム
def inventory_management():
conn = sqlite3.connect('inventory.db')
cursor = conn.cursor()
# 在庫切れ警告
cursor.execute('''
SELECT product_name, current_stock, min_stock
FROM inventory
WHERE current_stock <= min_stock
ORDER BY (min_stock - current_stock) DESC
''')
low_stock = cursor.fetchall()
# 在庫回転率
cursor.execute('''
SELECT product_name,
current_stock,
COALESCE(total_sold / current_stock, 0) as turnover_ratio
FROM inventory
LEFT JOIN (
SELECT product_id, SUM(quantity) as total_sold
FROM sales
WHERE sale_date >= date('now', '-30 days')
GROUP BY product_id
) sales_data ON inventory.product_id = sales_data.product_id
ORDER BY turnover_ratio DESC
''')
turnover = cursor.fetchall()
conn.close()
return low_stock, turnover
ベストプラクティス
セキュリティ対策
def security_practices():
# 1. パラメータ化クエリの使用
def safe_search(name, department):
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
cursor.execute(
"SELECT * FROM employees WHERE name = ? AND department = ?",
(name, department)
)
return cursor.fetchall()
# 2. 入力値検証
def validate_input(name, salary):
if not name or len(name.strip()) == 0:
raise ValueError("名前は必須です")
if not isinstance(salary, (int, float)) or salary < 0:
raise ValueError("給与は正の数値である必要があります")
return True
エラーハンドリング
class DatabaseManager:
def __init__(self, db_path):
self.db_path = db_path
def execute_query(self, query, params=None):
try:
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
result = cursor.fetchall()
conn.commit()
return result
except sqlite3.Error as e:
if conn:
conn.rollback()
raise Exception(f"データベースエラー: {e}")
finally:
if conn:
conn.close()
パフォーマンス監視
import time
from functools import wraps
def monitor_query(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
execution_time = time.time() - start_time
if execution_time > 1.0: # 1秒以上
print(f"遅いクエリ検出: {func.__name__} - {execution_time:.2f}秒")
return result
return wrapper
@monitor_query
def slow_query_example():
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM employees ORDER BY salary")
return cursor.fetchall()
まとめ
PythonとSQLの組み合わせは、データ駆動型アプリケーションの開発において強力な武器となります。基本的なCRUD操作から高度な分析クエリ、パフォーマンス最適化まで、段階的に理解を深めることが重要です。
重要なポイント:
- セキュリティ:パラメータ化クエリによるSQLインジェクション対策
- パフォーマンス:インデックスとバッチ処理による最適化
- 保守性:適切なエラーハンドリングとトランザクション管理
- スケーラビリティ:接続プールと監視システムの導入
- 可読性:動的クエリ構築とORMの適切な使用
実際のプロジェクトでは、データの性質とアプリケーションの要件に応じて、最適な技術選択を行うことが成功の鍵となります。SQLiteから始めて、必要に応じてより高機能なデータベースシステムへの移行を検討してください。
■「らくらくPython塾」が切り開く「呪文コーディング」とは?
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座
![]() |
20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード |
| |
週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ |
| |
10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks |




