2017-08-16 15 views
1

ここにその話があります。私はマスターテーブルから、そして名前がマスターテーブルの値に基づいている一連のテーブルからメタデータを取得しようとしています。外部キーはありません。スカラ変数にデータが入力されない

キーがあった場合は、マスターテーブルからのプライマリキーが子テーブルの末尾に追加されます。マスターテーブルはhsi.keytypetableです。子表はhsi.keyitemxxxです。ここで、xxxはマスター表から引き出された値(keytypenum)です。

私は今、子テーブルから取得しようとしているすべての値のカウントです。現在のフォームでは、@sql1のクエリは@keytypenumに設定されていませんが、クエリ自体を見て別のウィンドウで実行すると、それはチャンピオンのように機能します。問題は、スカラー変数「@keytypenum」

は、私の知る限り、私は宣言した宣言する必要があります

、私はエラーを取得しています2番目のクエリ、 @sql2、で継続しますもの。私は各クエリの構文に同様の問題があると推測しています。

SET CONCAT_NULL_YIELDS_NULL OFF 
declare @keytypedata table 
    (
     Keyword varchar(50), 
     DateType varchar(50), 
     "Length" int, 
     "Count" int 
    ) 

declare @keywordcount int 
declare @x int = 1 
declare @keytypenum int 
declare @sql1 varchar(max) 
declare @sql2 varchar(max) 

/* Determine how many records are in the master table so that I can cycle thru each one, getting the count of the child tables. */ 
Select @keywordcount = (Select count(*) from hsi.keytypetable) 

/* @x is the counter. I'll cycle through each row in the master using a WHILE loop */ 

WHILE @x < @keywordcount+1 
    BEGIN 

/* One row at a time, I'll pull the KEYTYPENUM and store it in @keytypenum. (I don't really need the order by, but I like having things in order!) 
** I take the rows in order b using my counter, @x, as the offset value and fetch only 1 row at a time. When I run this query in a separate screen, 
** it works well, obviously with providing a fixed offset value. */ 

     set @sql1 = 
      'Set @keytypenum = 
      (Select 
       KEYTYPENUM 
      from hsi.keytypetable 
      order by KEYTYPENUM 
      OFFSET ' + cast(@x as varchar(4)) + ' ROWS 
      FETCH NEXT 1 ROWS ONLY)' 
    EXEC(@sql1) 

/* For debugging purposes, I wanted to see that @keytypenum got assigned. This is working. */ 
print 'KeyTypeNum: '+cast(@keytypenum as varchar(4)) 

/* I don't know why I had to be my table variable, @keytypedata, in single quotes at the beginning, but it wouldn't work if 
** I didn't. The problem comes later on with restricting the query by the aforementioned @keytypenum. Remember this variable is an INT. All values 
** for this field are indeed integers, and there are presently 955 rows in the table. The maximum value is 1012, so we're safe with varchar(4). 
*/ 
    SET @sql2 = 
    'Insert into ' + '@keytypedata' + ' 
    Select 
     keytype, 
     CASE 
       WHEN k.datatype = 1 THEN ''Numeric 20'' 
       WHEN k.datatype = 2 THEN ''Dual Table Alpha'' 
       WHEN k.datatype = 3 THEN ''Currency'' 
       WHEN k.datatype = 4 THEN ''Date'' 
       WHEN k.datatype = 5 THEN ''Float'' 
       WHEN k.datatype = 6 THEN ''Numeric 9'' 
       WHEN k.datatype = 9 THEN ''DateTime'' 
       WHEN k.datatype = 10 THEN ''Single Table Alpha'' 
       WHEN k.datatype = 11 THEN ''Specific Currency'' 
       WHEN k.datatype = 12 THEN ''Mixed Case Dual Table Alpha'' 
       WHEN k.datatype = 13 THEN ''Mixed Case Single Table Alpha'' 
      END, 
      keytypelen, 
      (Select count(*) from hsi.keyitem' + cast(@keytypenum as varchar(4)) + ') 
    FROM 
     hsi.keytypetable k 
    where 
     k.keytypenum = ' + cast(@keytypenum as varchar(4))+'' 

/* Printing out where I am with cycling thru the master table, just for troubleshooting*/ 
print @x 

/* Increment the counter*/ 
    set @x = @x + 1 
END 

/* This query is simply to display the final results. */ 

select * 
from @keytypedata 
order by 1 

/* Print statements below are for troubleshooting. They should show what the 2 queries currently look like. */ 
Print @sql1 
Print @sql2 
+1

あなたの質問を書式設定し、[最小、*および*を確認する](https://stackoverflow.com/help/mcve)に* minimial *を付けて開始してください。 – scsimon

答えて

0

変数を宣言すると、可視性は宣言されているスコープに制限されます。ステートメントを実行すると、新しいセッションが作成され、新しいスコープが作成されます。 @sql変数はNVARCHARにする必要があることを

SET @sql='Set @keytypenum = ...'; 
EXEC sp_executesql @sql,N'@keytypenum INT OUT', @keytypenum OUTPUT; 

注:

何をする必要があると出力がsp_executesqlに電話でOUTPUTパラメータを使用して、スカラー変数です。

さらに多くの例が見つかりますhere

+0

これはすばらしいことで、最初の質問ですぐに私の問題を解決しました。あなたが気にしないなら、フォローアップの質問。私の2番目のクエリは、テーブル変数、keytypedataを使用します。この「仮想」表​​を使用して、結果のすべての結果を要約することを望んでいました。エラーが出ているので、 "テーブル変数@keytypedataを宣言しなければなりません。"私はテーブルに行を追加することができないことに懸念しています。これは、EXECごとにリセットされるためです。 sp_executesqlがそれを回避するのだろうか? :(大変ありがとうございます) – Brad

+0

@Brad Hi Brad。テーブル値のパラメータは常に読み取り専用で、出力には使用できません(詳細は[この質問](https://stackoverflow.com/q/19270727/243373)を参照してください)。あなたは一時テーブルを代わりに使うことができます。これらはパラメータとして渡す必要はありません。セッションがアクティブである限り、通常のテーブルであるかのように一時的に存在します。 –

+0

@ブラッド私の答えがあなたの問題を解決したら、その答えの横にあるチェックマーク(✔)をチェックしてください。ここで、[誰かが私の質問に答えるときに何をすべきですか?](https://stackoverflow.com/help/someone-answers)。 –

0

ええ、それはできません。あなたの変数は範囲外になります。

各変数のスコープは自分のセッションに限定されており、exec()は基本的に新しいセッションを作成します。

これがスローされますと@xが定義されていないことを示すエラー:

declare @x int = 1 

exec ('select @x') 

としてはこれます:

exec ('declare @x int = 2') 

exec ('select @x') 

そして、この:

exec ('declare @x int = 2') 

select @x 

あなたが好きそれをしなければならないだろうthis:

exec ('declare @x int = 2; select @x') 

それ以外の場合は結果を何とか返す。 @ TT。答えのsp_executesqlの提案はいい考えです。

関連する問題