😇
RailsでSQLを操作してみようーー!!
RailsSQL実行用メソッド 完全ガイド
Railsでデータベース操作を行う際、ActiveRecordが便利ですが、パフォーマンスが必要な場面や複雑なクエリでは生SQLを使いたいケースがあったので、本記事では、実務でよく使われる生SQL実行用メソッドと、それに対応するActiveRecordの書き方を20パターン紹介します。
基本知識
主要な生SQL実行メソッド
-
execute: 戻り値なし、INSERT/UPDATE/DELETE用 -
connection.execute: 結果を返す、SELECT用 -
connection.select_all: ハッシュ配列で結果を返す -
connection.select_value: 単一値を返す
1. 基本的なCRUD操作
1. データ挿入
# 生SQL
execute "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')"
# ActiveRecord
User.create(name: 'John', email: 'john@example.com')
2. データ更新
# 生SQL
execute "UPDATE users SET name = 'Jane' WHERE id = 1"
# ActiveRecord
User.find(1).update(name: 'Jane')
# または
User.where(id: 1).update_all(name: 'Jane')
3. データ削除
# 生SQL
execute "DELETE FROM users WHERE age < 18"
# ActiveRecord
User.where('age < ?', 18).delete_all
4. データ取得
# 生SQL
connection.execute("SELECT * FROM users WHERE age > 20")
# ActiveRecord
User.where('age > ?', 20)
2. テーブル構造変更(マイグレーション)
5. カラム追加
# 生SQL
execute "ALTER TABLE users ADD COLUMN phone VARCHAR(255)"
# ActiveRecord
add_column :users, :phone, :string
6. カラム削除
# 生SQL
execute "ALTER TABLE users DROP COLUMN phone"
# ActiveRecord
remove_column :users, :phone
7. インデックス追加
# 生SQL
execute "CREATE INDEX index_users_on_email ON users(email)"
# ActiveRecord
add_index :users, :email
8. インデックス削除
# 生SQL
execute "DROP INDEX index_users_on_email"
# ActiveRecord
remove_index :users, :email
3. 制約操作
9. NOT NULL制約追加
# 生SQL
execute "ALTER TABLE users ALTER COLUMN email SET NOT NULL"
# ActiveRecord
change_column_null :users, :email, false
10. 外部キー追加
# 生SQL
execute "ALTER TABLE posts ADD CONSTRAINT fk_posts_users FOREIGN KEY (user_id) REFERENCES users(id)"
# ActiveRecord
add_foreign_key :posts, :users
11. 外部キー削除
# 生SQL
execute "ALTER TABLE posts DROP FOREIGN KEY fk_posts_users"
# ActiveRecord
remove_foreign_key :posts, :users
4. 集計・複雑なクエリ
12. 集計クエリ
# 生SQL
connection.execute("SELECT COUNT(*) as count, status FROM orders GROUP BY status")
# ActiveRecord
Order.group(:status).count
13. サブクエリを使った更新
# 生SQL
execute "UPDATE users SET total_orders = (SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id)"
# ActiveRecord
User.left_joins(:orders).group('users.id').update_all('total_orders = COUNT(orders.id)')
14. 複数テーブルからの更新
# 生SQL
execute "UPDATE users u JOIN profiles p ON u.id = p.user_id SET u.name = p.full_name"
# ActiveRecord
User.joins(:profile).update_all('users.name = profiles.full_name')
15. CASE文を使った更新
# 生SQL
execute "UPDATE orders SET status = CASE WHEN amount > 1000 THEN 'premium' ELSE 'standard' END"
# ActiveRecord
Order.update_all("status = CASE WHEN amount > 1000 THEN 'premium' ELSE 'standard' END")
5. 実務で頻発する高度な操作
16. バルクインサート
# 生SQL
execute "INSERT INTO logs (message, created_at) VALUES ('msg1', NOW()), ('msg2', NOW())"
# ActiveRecord(Rails 6以降)
Log.insert_all([{message: 'msg1'}, {message: 'msg2'}])
17. TRUNCATE(全データ削除)
# 生SQL
execute "TRUNCATE TABLE temp_data"
# ActiveRecord(完全ではないが類似)
TempData.delete_all
18. シーケンスリセット
# 生SQL(PostgreSQL)
execute "ALTER SEQUENCE users_id_seq RESTART WITH 1"
# ActiveRecord
connection.reset_pk_sequence!(:users)
19. 条件付き一括更新
# 生SQL
execute "UPDATE products SET price = price * 0.9 WHERE category_id IN (1,2,3)"
# ActiveRecord
Product.where(category_id: [1,2,3]).update_all('price = price * 0.9')
20. JSON操作(PostgreSQL)
# 生SQL
execute "UPDATE users SET settings = jsonb_set(settings, '{theme}', '\"dark\"')"
# ActiveRecord(生SQLの方が推奨)
User.update_all("settings = jsonb_set(settings, '{theme}', '\"dark\"')")
使い分けのポイント
生SQLを使うべき場面
- 大量データの処理でパフォーマンスが重要
- 複雑なJOINやサブクエリが必要
- データベース固有の機能を使いたい
- マイグレーションでの細かい制御
ActiveRecordを使うべき場面
- 通常のCRUD操作
- 可読性を重視したい
- データベースに依存しないコードを書きたい
- Railsのバリデーションやコールバックを活用したい
まとめ
生SQLとActiveRecordはそれぞれ適した場面があります。基本的にはActiveRecordを使い、パフォーマンスや複雑性の要求に応じて生SQLを選択するのがベストプラクティスです。
特にマイグレーションでは、executeメソッドを使った生SQLが重宝するケースが多いので、ぜひ覚えておきましょう!!!
Discussion