2017-08-16 126 views
1

這是故事。我試圖從主表和一系列名稱基於主表中的值的表中提取元數據。沒有外鍵。標量變量不填充

如果有一個鍵,那就是來自主表的主鍵被附加到子表的末尾。主表是hsi.keytypetable。子表格是hsi.keyitemxxx,其中xxx是從主表中抽取的值(keytypenum)。

所有我想要從子表中拉現在是一個值的計數。在當前的表單中,查詢@sql1無法填充@keytypenum,但當我查看查詢本身並在單獨的窗口中運行它時,它的工作方式類似於冠軍。這個問題繼續在第二個查詢,@sql2,在那裏我得到的錯誤,

必須聲明標量變量「@keytypenum」

至於我可以告訴大家,我已經聲明瞭事情。我猜我在每個查詢中都有類似的語法問題。

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

當您聲明變量時,可見性僅限於聲明它們的範圍。當您執行語句時,會創建一個新的會話,從而創建一個新的範圍。

你需要做的是輸出使用呼叫的OUTPUT參數sp_executesql標量變量:

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

注意,@sql變量需要是一個NVARCHAR

你可以找到更多的例子here

+0

這真棒,很清楚地解決了我的問題,立即查詢第一個問題。跟進問題,如果你不介意。我的第二個查詢使用表變量,keytypedata。我希望用這個「虛擬」表來總結我的所有輸出結果。當我收到錯誤時,「必須聲明表變量@keytypedata」。我擔心我無法將行附加到表中,因爲它會在每次EXEC後重置。 sp_executesql會解決這個問題,還是我搞砸了? (非常感謝你! – Brad

+0

@Brad Hi Brad。表值參數總是隻讀的,不能用於輸出(參見[這個問題](https://stackoverflow.com/q/19270727/243373)你可以使用臨時表,而不必將它們作爲參數傳遞,只要會話處於活動狀態,它們暫時存在,就好像它們是普通表一樣, –

+0

@Brad如果我的答案解決了你的問題,請檢查答案旁邊的複選標記(✔)。閱讀更多關於此處的信息:[當某人回答我的問題時該怎麼辦?](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 

你必須要做得像這個:

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

或以其他方式將結果返回。 @ TT。答案中的sp_executesql建議是個不錯的主意。