DB検索結果をCSVに出力(テストデータ作成も含めて)

こんばんは
今回はDB検索結果を基にCSV出力したお話しを書きます。

目次

事の始まり

ある日仕事してるとき上司からT-SQL(ストアドプロシージャ)したことありますかと言われ、去年案件で初めてストアドプロシージャを使って処理を書いたことがあったので、YESと答えたところ、ある案件で下記の処理を行いたいとの話がありました。
その内容は
“テーブルに登録されているデータをルールに従って集計しCSV出力したい”
とのことです。

案件に携わる可能性があるので今のうちにちょっと知っとこうかなと思い、こちらの環境で予測しつつ書いてみました。

テストデータ作成

“登録されているデータをルールに従って集計”とのことで、集計ってcount関数とかそういうのじゃないですよね?って思いそこはわからなかったのですが、とりあえず今回の検証は個人的に作っているWEBアプリ(ゲームコレクターアプリ)で使用して入力されたソフト情報の記録先であるソフトウェアテーブルを使って、ハードウェアを抽出条件として検索した結果をCSVに出力します。

とりあえずテーブルやデータを1件だけ作ってありますが、数千件はレコードが欲しいなと思い、カラム(ハードウェア)を乱数でPS1やセガサターンなどが入ったレコードを作りたいと思い、調べつつストアドプロシージャを作成しました。

下記が、テストデータ作成用のストアドプロシージャです。
(一部DB名を修正してます)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
USE [DBNAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [proc_Create_TestData_Software]
AS
BEGIN
DECLARE @index INTEGER

--SOFTWARE_ID
SET @index = 1

--5000件作る
WHILE @index <= 5000
BEGIN
--変数宣言(型やサイズはカラム構成通りに宣言)
DECLARE @randomHdId NVARCHAR(30)
DECLARE @randomGenre NVARCHAR(10)

--ハードウェア値をランダム取得
SELECT TOP 1 @randomHdId = t_hardware.hardware_id FROM t_hardware ORDER BY NEWID();

--ジャンルもランダムで取得します(アクションやRPGとかです)
SELECT TOP 1 @randomGenre = m_genre.genre FROM m_genre ORDER BY NEWID();

--テストデータ作成(Insert文)
INSERT INTO t_software
VALUES
('TSID' + CONVERT(NVARCHAR,@index),
'test' + CONVERT(NVARCHAR,@index),
@randomHdId,
'testPub',
'testDev',
@randomGenre,
'testTag',
CURRENT_TIMESTAMP
);

--インクリメント
SET @index = @index + 1

END
END
GO

これで、まずクラステーブルのハードウェアテーブルやジャンルテーブルに入っているハードウェアIDとジャンルIDをランダムに取得しソフトウェアID(TSID1からTSID5000まで)を作成します。


結果が下記です。(数件のみ) ※2行目のレコードは実際にあるプレステソフトのデータです。
1
2
3
4
5
6
7
8
9
10
software_id	software_name	hardware_id	publisher_id	developer_id	genre	tags	modify_date
SLPS01577 必殺パチンコシミュレーション パチンコステーション モンスターハウススペシャル PS1 SUNSOFT-001 SUNSOFT-001 SLG シミュレーション,パチンコ,パチスロ 2024-09-07 11:35:00
TSID1 test1 N64 testPub testDev RCG testTag 2024-10-16 00:49:00
TSID10 test10 PCE testPub testDev RPG testTag 2024-10-16 00:49:00
TSID100 test100 NSW testPub testDev SLG testTag 2024-10-16 00:49:00
TSID1000 test1000 MG testPub testDev RPG testTag 2024-10-16 00:49:00
TSID1001 test1001 PCE testPub testDev SPT testTag 2024-10-16 00:49:00
TSID1002 test1002 WiiU testPub testDev MSLG testTag 2024-10-16 00:49:00
TSID1003 test1003 Steam testPub testDev SLG testTag 2024-10-16 00:49:00
TSID1004 test1004 Wii testPub testDev SLG testTag 2024-10-16 00:49:00

少し見ずらいですが、ハードやジャンルがランダムに取得してデータが作成されています。
ハード例:MG(メガドライブ),PCE(PCエンジン)
ジャンル例:SLG(シミュレーション),SPT(スポーツゲーム)

ORDER BY NEWID()によってランダムにテーブルがソートされることにより、 ランダムに値を取得することができます。

検索結果をCSVファイルとして出力

次はテストデータ作成したソフトウェアテーブルをハードウェアを抽出条件に指定して、
CSVファイルに出力します。
下記が作成したストアドプロシージャです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
USE [DBNAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

--引数で抽出条件のハードウェアIDを指定します。
CREATE PROCEDURE [proc_Select_To_CSV_Where_Hardware]
@hardware_id nvarchar(30)
AS
BEGIN
SET NOCOUNT ON;

--DBサーバーの情報と出力先とファイル名を宣言
DECLARE @SERVER VARCHAR(MAX) = 'localhost';
DECLARE @DATABASE VARCHAR(MAX) = 'DBNAME';
DECLARE @OUTFILE VARCHAR(MAX) = 'D:\temp\test.csv';

--ソフトウェアテーブルを検索
DECLARE @SQL VARCHAR(8000) = '';
select
@SQL += 'SELECT * FROM t_software '
,@SQL += 'where hardware_id = ''{HARDWARE}'''
,@SQL = REPLACE(@SQL,'{HARDWARE}' ,@hardware_id);

DECLARE @CMD VARCHAR(8000) = '';
--DOSコマンド用の文字列を代入
SELECT
@CMD += 'SQLCMD'
,@CMD += ' -S {SERVER}'
,@CMD += ' -d {DATABASE}'
,@CMD += ' -q "{SQL}"'
,@CMD += ' -s '','' -W'
,@CMD += ' -o {FILE}'
,@CMD = REPLACE(@CMD,'{SERVER}' ,@SERVER)
,@CMD = REPLACE(@CMD,'{DATABASE}',@DATABASE)
,@CMD = REPLACE(@CMD,'{SQL}' ,@SQL)
,@CMD = REPLACE(@CMD,'{FILE}' ,@OUTFILE)
;

--DOSコマンドを実行させるために構成オプションを変更するために実行
EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1
RECONFIGURE;

--CSV出力用のDOSコマンド実行
EXEC master..xp_cmdshell @CMD;
END
GO

各コメントの説明の通りです。

46行から48行までについてですが、
DOSコマンドを実行させるための”xp_cmdshell”を実行させるために
SQLServerのグローバル構成設定を変更させる必要があるそうです。
‘show advanced options’,1でシステムストアドプロシージャの拡張オプションを表示して、
‘xp_cmdshell’1にすることによりxp_cmdshellが使えるようになります。
RECONFIGUREで構成設定を更新することができます。

ストアドプロシージャ実行後、test.csvが出力されます。
一部内容です。(引数でPS2を指定)

1
2
3
4
5
6
7
8
software_id'software_name'hardware_id'publisher_id'developer_id'genre'tags'modify_date
-----------'-------------'-----------'------------'------------'-----'----'-----------
TSID1017'test1017'PS2'testPub'testDev'RCG'testTag'2024-10-16 00:49:00
TSID1036'test1036'PS2'testPub'testDev'SPT'testTag'2024-10-16 00:49:00
TSID1048'test1048'PS2'testPub'testDev'PZL'testTag'2024-10-16 00:49:00
TSID1202'test1202'PS2'testPub'testDev'AVG'testTag'2024-10-16 00:49:00
TSID124'test124'PS2'testPub'testDev'RCG'testTag'2024-10-16 00:49:00
TSID1240'test1240'PS2'testPub'testDev'RPG'testTag'2024-10-16 00:49:00

お疲れ様でした。

今回の記事のオススメ曲

この時期ですが、SNSでとんねるずがライブをやるとの記事をよく見かけ
野猿復活しないかな・・・と思い、野猿で一番好きな曲を載せます。
曲調も好きですが、あまり普段意識してない歌詞も好きです。


では、また次回。