質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Transact-SQL

Transact-SQLはSybase ASEとMIcrosoft SQLサーバで対応されているSQLの機能拡張版です。

Q&A

解決済

4回答

41173閲覧

T-SQL:SELECT結果を配列に入れる方法

dera

総合スコア28

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Transact-SQL

Transact-SQLはSybase ASEとMIcrosoft SQLサーバで対応されているSQLの機能拡張版です。

1グッド

1クリップ

投稿2018/01/15 06:52

編集2018/01/15 08:28

こんにちわ。T-SQL初心者です。
T-SQLで配列を使う方法を模索しております。
現状は、下記のようにカーソル文を用いて
データの数分だけFETCH NEXT~
をしているのですが、データの数が膨大になったとき、
手打ちでは追い付かないと考えました。

そこで、これらを配列で持たせる方法があれば
一々手打ちしなくてもよいと考えます。

しかし、それを実現する方法がわからず、
途方に暮れてしまいました。

皆様の力をお貸しください。

SQLSERVERは2014年です。

追記:C#ですと

C#

1//初期宣言 2var list = new list<string>() 3 4for(i = 0 i <= 9; i++){ 5 list.add(i.ToString()); 6}

イメージ的にはこんな感じかなと。
このようなことをT-SQLでできないかな・・。

T

1--カーソルの値を取得する変数宣言 2DECLARE @W_COL1 varchar(50) 3DECLARE @W_COL2 decimal(18,0) 4 5--カーソル定義 6DECLARE CUR_AAA CURSOR FOR 7 SELECT COL1 8 ,COL2 9 FROM TAB_A 10 WHERE TAB_A.COL1 = <条件値> 11 12--カーソルオープン 13OPEN CUR_AAA; 14 15--最初の1行目を取得して変数へ値をセット 16FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 17 18--データの行数分ループ処理を実行する 19WHILE @@FETCH_STATUS = 0 20BEGIN 21 22 -- ========= ループ内の実際の処理 ここから=== 23 24 1.ここにSELECT結果を配列としてSET 25 26 -- ========= ループ内の実際の処理 ここまで=== 27 28 29 --次の行のデータを取得して変数へ値をセット 30 FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 31 32END 33  2.配列結果のうち、@W_COL1を 34 IF文の条件として使用する。 35 3.IF分の中でさらにSELECT文を発行し、 36    WHERE句として使用する 37 38--カーソルを閉じる 39CLOSE CUR_AAA; 40DEALLOCATE CUR_AAA;
dotnetuseryamag👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sousuke

2018/01/15 07:06

ここでSELECT文発行(略)の部分で具体的に何を手打ちしているのか、何をしたいのか聞いたほうがいいと思います。現状の質問文では閲覧者は何もわかりません。
dera

2018/01/15 08:05

申し訳ありません。こちらの勘違いでしたので修正いたしました。 SELECT文発行~の箇所でSELECT結果を配列に入れたいと思っています。
sousuke

2018/01/15 08:14

可能なかぎりでいいので操作内容を伝えた方がいいですよ。どういう配列ができる予定なのか全くわかりません。
guest

回答4

0

ベストアンサー

こういうことですか?ただテーブルを作ってinsertするだけです。
それを作ってどうするのかが不明なのでアレなんですが…。

sql

1~~~~省略~~~~ 2CREATE TABLE #tmp 3 ( 4 W_COL1 varchar(50) NULL, 5 W_COL2 decimal(18, 0) NULL, 6 W2_COL1 varchar(50) NULL, 7 W2_COL2 decimal(18, 0) NULL 8 ) 9 10~~~~省略~~~~ 11WHILE @@FETCH_STATUS = 0 12BEGIN 13 14 -- ========= ループ内の実際の処理 ここから=== 15 16 insert #tmp (W_COL1,W_COL2,W2_COL1,W2_COL2) 17 select @W_COL1,@W_COL2,@W2_COL1,@W2_COL2 18 19 -- ========= ループ内の実際の処理 ここまで=== 20 21 22 --次の行のデータを取得して変数へ値をセット 23 FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 24 FETCH NEXT FROM CUR_AAA INTO @W2_COL1,@W2_COL2; 25 26END 27 28select * from #tmp 29

投稿2018/01/15 08:23

sousuke

総合スコア3830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dera

2018/01/15 08:29 編集

詳細を言葉で追記しました。 これは、テーブル変数というものを用いているということでしょうか? 試してみます。
sousuke

2018/01/15 08:30

テーブル変数に近いものだと思ってもらって結構です。ローカル一時テーブルと言うものです。
dera

2018/01/16 00:07

遅くなりました。 昨日試していたところ、SELECT結果をローカル一時テーブルに保持することで、配列みたく使うことができました。ありがとうございます。
guest

0

データの数が膨大になったとき、
手打ちでは追い付かないと考えました。

そこで、これらを配列で持たせる方法があれば
一々手打ちしなくてもよいと考えます。

何したいのかサッパリなので、理由は兎も角、
取り敢えず複数行に跨る項目を項目内に配列のように展開したいということであれば、
SQLで取得時に纏めることも可能ではあります。

t-sql group_concatなどのキーワードで検索してみて下さい。

カラムの値からカンマ区切り (CSV) の文字列を生成する

投稿2018/01/15 14:17

sazi

総合スコア25300

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  2.配列結果のうち、@W_COL1を IF文の条件として使用する。 3.IF分の中でさらにSELECT文を発行し、     WHERE句として使用する

この部分で本当にやりたいことが何なのか、次第でしょうか。
select文を発行するだけだとあまり意味がないように思えまして、select発行してその結果に対して何かをしたいのですよね、おそらく。
(結果をprintで表示したいとか、結果を元にinsertかupdateかをしたいとか……)
そのあたり、いかがでしょうか。

投稿2018/01/15 13:12

alg

総合スコア2019

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ちょっと FETCH している箇所の意図が(私が)理解できていない気がするのですが、

sql

1--最初の1行目を取得して変数へ値をセット 2FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 3FETCH NEXT FROM CUR_AAA INTO @W2_COL1,@W2_COL2;

上記では 1 つ目の FETCH で 「最初の 1 行目のデータ」、
その直後の FETCH で「2 行目のデータ」が取れるのではないかと思うのですが、これはそういう意図ですか?

そして WHILE の最後で FETCH している箇所では、

sql

1 --次の行のデータを取得して変数へ値をセット 2 FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 3 FETCH NEXT FROM CUR_AAA INTO @W2_COL1,@W2_COL2;

最初の FETCH で「3 行目のデータ」、
その直後の FETCH で「4 行目のデータ」
が取れるような気がするのですが・・・

普通にカーソルで一行ずつ取得する場合、WHILE の前で FETCH 1 回、WHILE の最後で FETCH 1 回とするように思うのですが、まずここについてどうでしょうか。
(@W2_COL1, @W2_COL2 がいらないのでは?と思ったのですが)


そして、本題の「配列を使いたい」というのはどの部分に関してでしょうか。

『 ここでSELECT文発行(略) 』 の結果を配列に入れたい、ということでしょうか?
それとも前述のカーソルの扱いについて何か問題があったのでしょうか。

追記

IF分の中でさらにSELECT文を発行し、WHERE句として使用する

この SELECT したものは何に使うのでしょうか。PRINT で確認するだけ?

FETCH したものをそのまま判定に使ったり WHERE句 で指定したりするだけなら
配列に詰めないで WHILE の中でそのまま処理を書いてしまえば良い気もしますが。

以下 コピペで動くはず・・・
(2つ目のSELECTは適当です)
(TAB_A, TAB_B はテスト実行用にサブクエリを書いていますが、実際には普通にテーブルを指定すれば良いです)

sql

1BEGIN 2 --カーソルの値を取得する変数宣言 3 DECLARE @W_COL1 varchar(50) 4 DECLARE @W_COL2 decimal(18,0) 5 6 --2つ目の SELECT の結果を入れる変数 7 DECLARE @W_HOGE varchar(100) 8 9 --カーソル定義 10 DECLARE CUR_AAA CURSOR LOCAL FOR 11 SELECT COL1, COL2 12 FROM ( 13 SELECT 'aaa' AS COL1, CONVERT(decimal, 100) AS COL2 UNION ALL 14 SELECT 'bbb' AS COL1, CONVERT(decimal, 200) AS COL2 UNION ALL 15 SELECT 'ccc' AS COL1, CONVERT(decimal, 300) AS COL2 UNION ALL 16 SELECT 'aaa' AS COL1, CONVERT(decimal, 10) AS COL2 UNION ALL 17 SELECT 'aaa' AS COL1, CONVERT(decimal, 20) AS COL2 18 ) TAB_A 19 WHERE TAB_A.COL1 IN ('aaa', 'ccc') 20 21 --カーソルオープン 22 OPEN CUR_AAA; 23 24 --最初の1行目を取得して変数へ値をセット 25 FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 26 27 --データの行数分ループ処理を実行する 28 WHILE @@FETCH_STATUS = 0 29 BEGIN 30 31 -- 確認用 32 PRINT 'FETCHしたもの:[' + @W_COL1 + '] [' + CONVERT(varchar, @W_COL2) + ']' 33 34 -- ★FETCH した値を判定条件に使用 35 IF @W_COL1 = 'aaa' 36 BEGIN 37 -- FETCH した値を元に別テーブルを SELECT 38 SELECT @W_HOGE = Hoge 39 FROM ( 40 SELECT 'aaa' AS COL1, CONVERT(decimal, 100) AS COL2, 'hoge1' AS Hoge UNION ALL 41 SELECT 'bbb' AS COL1, CONVERT(decimal, 200) AS COL2, 'hoge2' AS Hoge UNION ALL 42 SELECT 'ccc' AS COL1, CONVERT(decimal, 300) AS COL2, 'hoge3' AS Hoge UNION ALL 43 SELECT 'aaa' AS COL1, CONVERT(decimal, 10) AS COL2, 'hoge4' AS Hoge UNION ALL 44 SELECT 'aaa' AS COL1, CONVERT(decimal, 20) AS COL2, 'hoge5' AS Hoge 45 ) TAB_B 46 WHERE TAB_B.COL1 = @W_COL1 --★WHERE句に使用 47 AND TAB_B.COL2 = @W_COL2 --★WHERE句に使用 48 49 -- 確認用 50 PRINT 'Hoge[' + @W_HOGE + ']' 51 END 52 ELSE 53 BEGIN 54 -- 確認用 55 PRINT '2つ目のSELECTは実行しません' 56 END 57 58 PRINT '----------' 59 60 --次の行のデータを取得して変数へ値をセット 61 FETCH NEXT FROM CUR_AAA INTO @W_COL1,@W_COL2; 62 END 63 64 --カーソルを閉じる 65 CLOSE CUR_AAA; 66 DEALLOCATE CUR_AAA; 67 68END

参考までに。

投稿2018/01/15 07:15

編集2018/01/15 09:15
sk_3122

総合スコア1126

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dera

2018/01/15 08:06 編集

申し訳ありません。こちらの勘違いがありましたので、 修正いたしました。 SELECT文は既に例の通り作成してあるので、 ループの中で配列として変数に格納したいということになります。 また、先ほどの例は例えばデータが2行しかない場合には こうかくことができるが、大量のデータが来た場合には どうすればよいのだろう?ということで記しました。 最後のFETCH NEXT~がないと、PRINT関数を用いて 出力結果を確認する際に表示されなかったため、 このような記述となっております。
sk_3122

2018/01/15 08:17

あーーーーーー FETCH した結果を 配列に持ちたいということですね。理解しました。 というか、FETCH したものを どう使いたいのでしょうか? たとえば FETCH したものを元にテーブルを更新、などとしたいのであれば WHILE の中に UPDATE 文を書いてしまえば良いのではないかと思うのですが、 戻り値として返す等したいのでしょうか? どうしても変数に入れたいということであれば「テーブル変数」とかですかね・・・?
dera

2018/01/15 08:24

それでいうと 1.上記カーソル文でSELECT結果を配列に格納し保持する 2.格納した配列を使いループ処理 3.ループ処理の中で取り出したものをさらに別テーブルのSELECT文の  条件分岐(IF文)で扱う といった流れになります。わかりますでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問