【DB】ストアドプロシージャ(STORED PROCEDURE)について
ストアドプロシージャとは
ストアドプロシージャを作ってみよう
1.準備
準備するもの
2.【Docker】データベースを作成
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=YourPassword123!" -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2019-latest
コマンドの詳細
-e "ACCEPT_EULA=Y" → マイクロソフトのライセンス契約に同意
-e "MSSQL_SA_PASSWORD=Password123" → 管理者(sa)のパスワードを設定
-p 1433:1433 → コンテナの1433番ポートをホストの1433番ポートに接続
--name sqlserver → コンテナに「sqlserver」という名前を付与
-d → バックグラウンドで実行(デタッチモード)
mcr.microsoft.com/mssql/server:2019-latest → マイクロソフト公式のSQL Server 2019イメージを使用
docker ps
コマンドの詳細
COMMAND CREATED STATUS PORTS NAMES
60c9beb7e72c mcr.microsoft.com/mssql/server:2019-latest "/opt/mssql/bin/perm…" 4 minutes ago Up 4 minutes 0.0.0.0:1433->1433/tcp sqlserver
3.【SSMS】サーバー接続
SQL Server Management Studio(SSMS)からサーバーに接続する手順

SSMSの画面からファイル>オブジェクトエクスプローラーの接続から画面を起動し、接続を行う

注意の画面がでてくるので、画面のAdvancedから画面の選択部分をFlaseからTrueへ変更する

接続完了
4.【SSMS】データベースの作成
CREATE DATABASE ShopDB
COLLATE Japanese_CI_AS;
GO

SSMSの新しいクエリを開き、「CREATE DATABASE DB_NAME」と入力しF5キーを押して実行し、DBを作成する
5.【SSMS】テーブルの作成
テーブル作成クエリ
-- 作成したデータベースを使用
USE ShopDB;
GO
-- 1. 顧客テーブル
CREATE TABLE Customers (
CustomerID INT IDENTITY(1,1) PRIMARY KEY,
CustomerName NVARCHAR(50) NOT NULL,
Email NVARCHAR(100) UNIQUE,
Phone NVARCHAR(20),
Address NVARCHAR(200),
RegistrationDate DATETIME2 DEFAULT GETDATE()
);
-- 2. カテゴリテーブル
CREATE TABLE Categories (
CategoryID INT IDENTITY(1,1) PRIMARY KEY,
CategoryName NVARCHAR(50) NOT NULL,
Description NVARCHAR(200)
);
-- 3. 商品テーブル
CREATE TABLE Products (
ProductID INT IDENTITY(1,1) PRIMARY KEY,
ProductName NVARCHAR(100) NOT NULL,
CategoryID INT NOT NULL,
Price DECIMAL(10,2) NOT NULL,
Stock INT NOT NULL DEFAULT 0,
Description NVARCHAR(500),
CreatedDate DATETIME2 DEFAULT GETDATE(),
FOREIGN KEY (CategoryID) REFERENCES Categories(CategoryID)
);
-- 4. 注文テーブル
CREATE TABLE Orders (
OrderID INT IDENTITY(1,1) PRIMARY KEY,
CustomerID INT NOT NULL,
OrderDate DATETIME2 DEFAULT GETDATE(),
Status NVARCHAR(20) DEFAULT '処理中' CHECK (Status IN ('処理中', '発送済み', '完了', 'キャンセル')),
TotalAmount DECIMAL(12,2) DEFAULT 0,
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);
-- 5. 注文詳細テーブル
CREATE TABLE OrderDetails (
OrderDetailID INT IDENTITY(1,1) PRIMARY KEY,
OrderID INT NOT NULL,
ProductID INT NOT NULL,
Quantity INT NOT NULL,
UnitPrice DECIMAL(10,2) NOT NULL,
Subtotal AS (Quantity * UnitPrice) PERSISTED,
FOREIGN KEY (OrderID) REFERENCES Orders(OrderID),
FOREIGN KEY (ProductID) REFERENCES Products(ProductID)
);

作成したDBのテーブルディレクトリの中にテーブルが作成される
6.【SSMS】テストデータの挿入
テストデータの挿入クエリ
-- サンプルデータ挿入
-- カテゴリデータ
INSERT INTO Categories (CategoryName, Description) VALUES
('電子機器', 'スマートフォン、パソコン、家電製品'),
('書籍', '小説、技術書、雑誌'),
('衣類', '洋服、靴、アクセサリー'),
('食品', '生鮮食品、加工食品、飲料');
-- 顧客データ
INSERT INTO Customers (CustomerName, Email, Phone, Address) VALUES
('田中太郎', 'tanaka@email.com', '090-1234-5678', '東京都渋谷区1-1-1'),
('佐藤花子', 'sato@email.com', '090-2345-6789', '大阪府大阪市2-2-2'),
('鈴木次郎', 'suzuki@email.com', '090-3456-7890', '愛知県名古屋市3-3-3'),
('高橋美咲', 'takahashi@email.com', '090-4567-8901', '福岡県福岡市4-4-4');
-- 商品データ
INSERT INTO Products (ProductName, CategoryID, Price, Stock, Description) VALUES
('iPhone 15', 1, 128000.00, 50, '最新のスマートフォン'),
('MacBook Air', 1, 148000.00, 30, '薄型軽量ノートパソコン'),
('ワイヤレスイヤホン', 1, 25000.00, 100, 'ノイズキャンセリング機能付き'),
('SQL入門書', 2, 3200.00, 200, 'データベース学習の基礎本'),
('プログラミング本', 2, 4500.00, 150, 'Python入門書'),
('ビジネススーツ', 3, 45000.00, 80, '高品質なビジネス用スーツ'),
('カジュアルシャツ', 3, 5500.00, 120, '普段着用のシャツ'),
('プレミアム米', 4, 8000.00, 300, '新潟県産コシヒカリ 10kg'),
('オーガニック野菜セット', 4, 2500.00, 50, '無農薬野菜の詰め合わせ');
-- 注文データ
INSERT INTO Orders (CustomerID, OrderDate, Status, TotalAmount) VALUES
(1, '2024-01-15 10:30:00', '完了', 0), -- 後でストアドプロシージャで計算
(1, '2024-01-20 14:15:00', '発送済み', 0),
(2, '2024-01-18 09:45:00', '完了', 0),
(3, '2024-01-22 16:20:00', '処理中', 0),
(4, '2024-01-25 11:10:00', '処理中', 0);
-- 注文詳細データ
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
-- 田中太郎の1回目の注文
(1, 1, 1, 128000.00), -- iPhone 15
(1, 4, 2, 3200.00), -- SQL入門書 2冊
-- 田中太郎の2回目の注文
(2, 3, 1, 25000.00), -- ワイヤレスイヤホン
-- 佐藤花子の注文
(3, 2, 1, 148000.00), -- MacBook Air
(3, 5, 1, 4500.00), -- プログラミング本
-- 鈴木次郎の注文
(4, 6, 1, 45000.00), -- ビジネススーツ
(4, 7, 2, 5500.00), -- カジュアルシャツ 2枚
-- 高橋美咲の注文
(5, 8, 1, 8000.00), -- プレミアム米
(5, 9, 3, 2500.00); -- オーガニック野菜セット 3個
テストデータ作成確認クエリ
SELECT 'Database Created Successfully' AS Status;
-- データ確認
SELECT CustomerName, Email FROM Customers;
-- リレーション確認
SELECT
c.CustomerName AS CustomerName,
o.OrderID,
o.OrderDate,
p.ProductName,
cat.CategoryName,
od.Quantity,
od.UnitPrice,
od.Subtotal
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
JOIN OrderDetails od ON o.OrderID = od.OrderID
JOIN Products p ON od.ProductID = p.ProductID
JOIN Categories cat ON p.CategoryID = cat.CategoryID
ORDER BY c.CustomerName, o.OrderDate;

テストデータが挿入されているかを確認する
7.【SSMS】ストアドプロシージャを作成

DB内のプログラミング>ストアドプロシージャ>新規作成>ストアドプロシージャから新規にストアドプロシージャを作成する
ストアドプロシージャの雛形
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name> -- 作成者名
-- Create date: <Create Date,,> -- 作成日
-- Description: <Description,,> -- 説明
-- =============================================
CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
-- Add the parameters for the stored procedure here
<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>,
<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
END
GO
ANSI_NULLSとSET QUOTED_IDENTIFIERについて
-- 例:こんなデータがあるとします
ProductName Price
iPhone 15 128000.00
Test Product NULL ← この行にNULL値
-- ANSI_NULLS ON の場合
WHERE Price IS NULL → Test Productの行が返される ✓
WHERE Price = NULL → 何も返されない ✗
-- ANSI_NULLS OFF の場合
WHERE Price IS NULL → Test Productの行が返される ✓
WHERE Price = NULL → Test Productの行が返される ✓(非標準)
-- QUOTED_IDENTIFIER ON の場合
'iPhone 15' → 文字列として扱われる ✓
"iPhone 15" → エラー!文字列として認識されない ✗
"ProductName" → 列名として扱われる ✓
-- QUOTED_IDENTIFIER OFF の場合
'iPhone 15' → 文字列として扱われる ✓
"iPhone 15" → 文字列として扱われる ✓(非標準)
"ProductName" → 文字列として扱われる(列名ではない)

「Ctrl」+「Shift」+「M」でパラメータ設定画面が開くので入力する
プロシージャ設定と定義とパラメータ定義と処理の記述
SET ANSI_NULLS ON GO -- ANSI_NULLS ON = NULL比較は IS NULL / IS NOT NULL を使うという宣言
SET QUOTED_IDENTIFIER ON GO -- QUOTED_IDENTIFIER ON = 文字列は 'シングルクォーテーション' を使うという宣言
-- =============================================
-- Author: <Author,,Name> -- 作成者名
-- Create date: <Create Date,,> -- 作成日
-- Description: <Description,,> -- 説明
-- =============================================
CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>,
<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
BEGIN
SET NOCOUNT ON;
-- 他の処理...
END
BEGIN -- プロシージャの処理の開始を示す
-- ここに実際の処理を書く
END -- プロシージャの処理の終了を示す
9.【SSMS】完成したストアドプロシージャ
完成したストアドプロシージャ
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: pyusuket
-- Create date: 2025-07-27
-- Description: 価格範囲で商品検索
-- =============================================
CREATE PROCEDURE sp_SearchProducts
@CategoryID int = NULL, -- カテゴリーID
@MinPrice DECIMAL(10,2) = 0, -- 最低価格
@MaxPrice DECIMAL(10,2) = 999999 -- 最高価格
AS
BEGIN
SET NOCOUNT ON;
-- 商品検索の実際の処理
SELECT
p.ProductID,
p.ProductName,
c.CategoryName,
p.Price,
p.Stock,
p.Description
FROM Products p
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
WHERE
-- カテゴリーIDが指定されている場合のみフィルタ
(@CategoryID IS NULL OR p.CategoryID = @CategoryID)
-- 価格範囲でフィルタ
AND p.Price BETWEEN @MinPrice AND @MaxPrice
-- 在庫があるもののみ
AND p.Stock > 0
ORDER BY p.Price ASC;
-- 検索結果の件数を返す(オプション)
SELECT COUNT(*) AS SearchResultCount
FROM Products p
WHERE
(@CategoryID IS NULL OR p.CategoryID = @CategoryID)
AND p.Price BETWEEN @MinPrice AND @MaxPrice
AND p.Stock > 0;
END
GO

実行するとストアドプロシージャが作成されている
10.ストアドプロシージャの実行
EXEC sp_SearchProducts;

プロシージャを実行し、以下の結果が得られれば成功
プロシージャの実行パターン
-- 1. 基本形:EXEC プロシージャ名
EXEC sp_HelloWorld;
-- 2. EXECUTEと書いてもOK(同じ意味)
EXECUTE sp_HelloWorld;
-- 3. パラメータなしの場合、EXECを省略可能
sp_HelloWorld;
11.【SSMS】パラメータを指定して実行してみる
EXEC sp_SearchProducts @MinPrice = 4000, @MaxPrice = 50000

パラメータを指定しないと9件だが指定すると5件になる
Discussion