はじめに
LLMへのプロンプト例、とくに「SQLクエリの作成をさせたもの」を忘備録として挙げておきます。
LLMにある程度しっかり(適当すぎるとダメだけど、完璧じゃなくてもなんとかなる)プロンプトを書くと、わりとそのまま使えるようなコードを書いてくれます。そのまま使えなくとも手直ししたら十分なものになります。一から自分で書くよりも速いですし、プロンプトを書くことを通して自分のなかでも整理されます。あえて複数パターンかかせて、違いやメリットデメリットをきくと勉強にもなります。
例文
投稿用に、元々のプロンプトを一般的な内容になるようにLLMに書き替えさせたうえで掲載しています。
・ストアドの作成1
以下の要件を満たすストアドプロシージャ「SP_CalcMonthlyReport」を作成したい。
概要:テーブル「WorkLog」(作業ログ)のデータをもとに、テーブル「MonthlyReport」(月次レポート)を更新・挿入する。
■ 使用テーブル・カラム
1. WorkLog テーブル
- EmpId CHAR(8) -- 社員(利用者)ID
- LogDate DATE -- 作業日
- Minutes INT -- 作業時間(分単位)
2. MonthlyReport テーブル
- EmpId CHAR(8) -- 社員(利用者)ID
- YearMonth VARCHAR(7) -- 対象年月(YYYY-MM)
- TotalMin INT -- 月間合計作業時間(分)
■ ストアド引数
- @EmpId CHAR(8)
- @YearMonth VARCHAR(7)
■ 処理内容
1. 引数の @EmpId、@YearMonth に合致する WorkLog の行を抽出。該当データがなければ終了。
2. 抽出した行の Minutes を合計し、MonthlyReport の TotalMin に設定。
- 該当レコードが存在しない場合は INSERT
- 既存レコードがある場合は UPDATE
返答例
CREATE PROCEDURE dbo.SP_CalcMonthlyReport
@EmpId CHAR(8),
@YearMonth VARCHAR(7) -- フォーマット: 'YYYY-MM'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TotalMin INT;
-- 1. 指定社員・年月の WorkLog を集計
SELECT @TotalMin = SUM(Minutes)
FROM dbo.WorkLog
WHERE EmpId = @EmpId
AND CONVERT(CHAR(7), LogDate, 120) = @YearMonth;
-- 該当データなしなら終了
IF @TotalMin IS NULL
RETURN;
-- 2. MonthlyReport に既存レコードがあるか判定
IF EXISTS (
SELECT 1
FROM dbo.MonthlyReport
WHERE EmpId = @EmpId
AND YearMonth = @YearMonth
)
BEGIN
-- 既存レコードなら UPDATE
UPDATE dbo.MonthlyReport
SET TotalMin = @TotalMin
WHERE EmpId = @EmpId
AND YearMonth = @YearMonth;
END
ELSE
BEGIN
-- レコード不存在なら INSERT
INSERT INTO dbo.MonthlyReport (EmpId, YearMonth, TotalMin)
VALUES (@EmpId, @YearMonth, @TotalMin);
END
END
GO
・ストアドの作成2
以下の要件を満たすストアドプロシージャ「SP_UpdateWorkDuration」を作成したい。
■ 概要
「DailyWorkLog」テーブルに記録された「開始時刻」と「終了時刻」から、作業時間(分単位)を算出し、「作業時間」列に更新する。
■ 対象テーブル:DailyWorkLog
-EmpId :CHAR(8) --社員ID
-WorkDate :DATE --作業日
-StartTime :CHAR(5) --開始時刻(HH:mm形式)
-EndTime :CHAR(5) --終了時刻(HH:mm形式)
-DurationMin :INT --作業時間(分)
■ ストアドの引数
- @EmpId CHAR(8)
- @WorkDate DATE
■ 処理内容
1. @EmpId および @WorkDate に一致する DailyWorkLog の行を1件取得。該当行がなければ処理終了。
2. 該当行の StartTime または EndTime のいずれかが NULL または空文字列であれば処理終了。
3. StartTime および EndTime を HH:mm 形式として TIME 型に変換し、差分(分)を計算。
4. 計算結果(分)を DurationMin に更新。
※ 開始時刻と終了時刻は文字列(CHAR(5), 'HH:mm')として管理されているため、適切なパース処理が必要。
返答例
CREATE PROCEDURE SP_UpdateWorkDuration
@EmpId CHAR(8),
@WorkDate DATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@sTime CHAR(5),
@eTime CHAR(5),
@tStart TIME(0),
@tEnd TIME(0),
@duration INT;
-- 1. 対象行の取得
SELECT
@sTime = StartTime,
@eTime = EndTime
FROM DailyWorkLog
WHERE EmpId = @EmpId
AND WorkDate = @WorkDate;
-- 該当行なしなら終了
IF @@ROWCOUNT = 0
RETURN;
-- 2. 時刻文字列の NULL または空文字チェック
IF @sTime IS NULL OR LTRIM(RTRIM(@sTime)) = ''
OR @eTime IS NULL OR LTRIM(RTRIM(@eTime)) = ''
BEGIN
RETURN;
END
-- 3. 文字列 → TIME 型に変換(パース)し、例外時は終了
BEGIN TRY
SET @tStart = CONVERT(TIME(0), @sTime, 108);
SET @tEnd = CONVERT(TIME(0), @eTime, 108);
END TRY
BEGIN CATCH
RETURN;
END CATCH
-- 差分(分単位)を計算
SET @duration = DATEDIFF(MINUTE, @tStart, @tEnd);
-- 4. 更新
UPDATE DailyWorkLog
SET DurationMin = @duration
WHERE EmpId = @EmpId
AND WorkDate = @WorkDate;
END
GO
・テーブル値関数の作成
以下の要件を満たすテーブル値関数「UF_GetWorkdaysOfMonth」を作成したい。
■ 概要
指定された年月(例: '2025-07')に存在するすべての日付を列挙し、各日付が「平日か休日か」を示す情報を付加して返す。
■ 引数
- @YearMonth VARCHAR(7)
※ 形式は 'YYYY-MM'
■ 返却されるテーブル構成(戻り値)
- WorkDate DATE --対象年月に含まれる日付
- IsWorkday CHAR(1) --平日なら '1'、休日なら '0'
■ 判定仕様
- 土曜日・日曜日を「休日」とし、それ以外を「平日」とみなす
- 祝日等の判定は含めない(必要に応じて別テーブルで拡張可能)
■ 例:`SELECT * FROM UF_GetWorkdaysOfMonth('2025-07')`
→ 2025年7月1日~31日の各日について、曜日に応じたフラグが表示される
返答例
CREATE FUNCTION UF_GetWorkdaysOfMonth
(
@YearMonth VARCHAR(7) -- 例: '2025-07'
)
RETURNS TABLE
AS
RETURN
WITH DateRange AS (
-- 開始日と終了日を計算(1日~末日)
SELECT
CAST(@YearMonth + '-01' AS DATE) AS StartDate,
EOMONTH(CAST(@YearMonth + '-01' AS DATE)) AS EndDate
),
Numbers AS (
-- 最大31日分の数列(0~30)を生成
SELECT TOP 31 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
FROM master.dbo.spt_values
),
AllDates AS (
-- 開始日 + n日 を加算して当月の日付を生成
SELECT DATEADD(DAY, n, StartDate) AS WorkDate
FROM DateRange
CROSS JOIN Numbers
WHERE DATEADD(DAY, n, StartDate) <= EndDate
)
-- 曜日判定(土日を休日、それ以外を平日)
SELECT
WorkDate,
CASE
WHEN DATEPART(WEEKDAY, WorkDate) IN (1, 7) THEN '0' -- 日曜=1, 土曜=7(SET DATEFIRST の既定値に依存)
ELSE '1'
END AS IsWorkday
FROM AllDates
・テーブル値関数の修正
以下の要件を満たすテーブル値関数「UF_GetWorkdaysByCutoff」を作成・修正したい。
■ 概要
指定された任意の日付(@TargetDate)をもとに、締め日基準の1か月間の出勤対象日(勤務日)を返す。
この関数は、もともと「月初〜月末」の範囲を対象としていた「UF_GetWorkdaysOfMonth」関数の代替として利用する。
■ 主な修正点
引数の変更
- 【旧】@YearMonth (VARCHAR(7))
- 【新】@TargetDate (DATE)
→ 指定された日付をもとに、締め日ロジックで判断する。
締め日による判定
- 締め日は別テーブル「Config_WorkSettings」の「CutoffDay」列から取得する。
- WHERE 設定種別 = 'CUTOFF_DAY'
- CutoffDay は 1~31 の整数で格納されている
- 指定された @TargetDate が「締め日より後」の場合 → 当月扱い
- 締め日以前(含む)の場合 → 前月扱い
対象期間の例(例:締め日=20)
指定日 対象期間
2025-07-10 2025/06/21~2025/07/20
2025-07-25 2025/07/21~2025/08/20
■ 返却されるテーブル構成
WorkDate DATE 該当期間に含まれる日付
IsWorkday CHAR(1) 平日なら '1'、休日なら '0'
※ 土日を休日とし、平日のみを '1' とする(祝日除外)
返答例
CREATE FUNCTION UF_GetWorkdaysByCutoff
(
@TargetDate DATE -- 例: '2025-07-10'
)
RETURNS TABLE
AS
RETURN
WITH Cutoff AS (
-- 締め日(1~31)を取得
SELECT CAST(CutoffDay AS INT) AS CutoffDay
FROM Config_WorkSettings
WHERE 設定種別 = 'CUTOFF_DAY'
),
RangeBase AS (
SELECT
C.CutoffDay,
-- ターゲット日の日付成分
DAY(@TargetDate) AS TargetDay,
-- ターゲット日の月初・前月・翌月補助
EOMONTH(@TargetDate) AS ThisMonthEnd,
EOMONTH(DATEADD(MONTH, -1, @TargetDate)) AS PrevMonthEnd
FROM Cutoff C
),
Period AS (
SELECT
-- 期間開始日と終了日を算出
CASE
WHEN TargetDay > CutoffDay THEN DATEFROMPARTS(YEAR(@TargetDate), MONTH(@TargetDate), CutoffDay + 1)
ELSE DATEFROMPARTS(YEAR(DATEADD(MONTH, -1, @TargetDate)), MONTH(DATEADD(MONTH, -1, @TargetDate)), CutoffDay + 1)
END AS StartDate,
CASE
WHEN TargetDay > CutoffDay THEN DATEFROMPARTS(YEAR(DATEADD(MONTH, 1, @TargetDate)), MONTH(DATEADD(MONTH, 1, @TargetDate)), CutoffDay)
ELSE DATEFROMPARTS(YEAR(@TargetDate), MONTH(@TargetDate), CutoffDay)
END AS EndDate
FROM RangeBase
),
Tally AS (
-- 最大日数用の連番(0〜62日分)
SELECT TOP 62 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS n
FROM master.dbo.spt_values
),
Dates AS (
SELECT DATEADD(DAY, n, P.StartDate) AS WorkDate
FROM Tally
CROSS JOIN Period P
WHERE DATEADD(DAY, n, P.StartDate) <= P.EndDate
)
SELECT
WorkDate,
CASE
WHEN DATEPART(WEEKDAY, WorkDate) IN (1, 7) THEN '0' -- 日曜:1, 土曜:7(デフォルト設定)
ELSE '1'
END AS IsWorkday
FROM Dates;
・スカラー値関数
以下の要件を満たすスカラー値関数「UF_GetAssignedBranch」を作成したい。
■ 概要
指定された従業員IDから、対応する所属拠点番号(BranchNo)を取得して返す。
■ 引数
- @EmpCode CHAR(4)
→ 従業員IDを表す
■ 対象テーブル:EmployeeMaster
- EmpCode CHAR(4) --従業員ID
- BranchNo DECIMAL(3,0) --所属拠点番号
■ 処理内容
EmployeeMaster テーブルから、EmpCode が引数と一致する行を検索し、該当する BranchNo を返却する。
■ 注意点
- 該当する従業員が存在しない場合は `NULL` を返す。
返答例
CREATE FUNCTION UF_GetAssignedBranch
(
@EmpCode CHAR(4)
)
RETURNS DECIMAL(3, 0)
AS
BEGIN
DECLARE @BranchNo DECIMAL(3, 0);
SELECT @BranchNo = BranchNo
FROM EmployeeMaster
WHERE EmpCode = @EmpCode;
RETURN @BranchNo;
END
おわりに
微妙だなってこともあれば、そう書いたらいいのか!ってこともあります。
効率的になっているし、学びもあるとも思うけれども、「一から自分で書く力」 については落ちてきているかもしれません。出来上がったコードをしっかり理解することは怠らないようにしたいです。