2011-06-27 46 views
0

我在SQL Server 2008中遇到了一個誤導性的錯誤,我想知道有沒有人可以解釋發生在我身上的事情?奇怪的SQL Server表的變量延遲加載?

我有一個存儲過程是這樣的:

declare @cross_reference table (
     context varchar(20) not null 
    , value1  varchar(10) not null 
    , value2  varchar(10) not null 
) 

insert into @cross_reference values ('map', 'from_value', 'to_value') 
insert into @cross_reference values ('map', 'from_value', 'to_value') 
insert into @cross_reference values ('map', 'from_value_xxxxx', 'to_value_xxxxxxx') 

select 
    t1.field1 
    , t1.field2 
    , xref.value2 
from table_1 t1 
inner join table_2 t2 on t2.id = t1.id 
left join @cross_reference xref on xref.context = 'map' and xref.value1 = t2.map_id 

的實際存儲過程是比較複雜的,但是這是要點。

運行SP後,我得到一個輸出行的負載之前,它的錯誤「字符串或二進制數據將被截斷」。錯誤中的特定行引用指向上面主SELECT語句中的某處,但在調試了一段時間後,我發現我在開始時將交叉引用放入的值太大,並且修復了它。

但我的問題是:

  • 如何在SQL服務器執行主SELECT語句,而無需插入完成交叉引用行?是否有某種延遲處理?表變量的延遲加載?

  • 爲什麼地球上「字符串或二進制數據將被截斷」的消息不是指向它實際發生的地方?還是我做錯了?

感謝, 雷

編輯

我覺得一定有什麼做的LEFT JOIN表中的變量,並且沒有它的列所涉及的WHERE子句。 SQL Server似乎已經將表的準備工作留在了需要的地方(INNER JOINs完成之後),並且在該點已經將大部分結果集準備就緒時出現錯誤。

我也注意到,成功插入到@cross_reference中的值確實顯示在返回的結果集中。而無法插入太大的行只顯示NULL。

回答

1

只是因爲發生了錯誤,並不能阻止存儲的進程繼續進行。您不會看到錯誤消息,因爲默認情況下,SSMS將顯示結果網格,直到查詢完成處理。

這表明10秒的成績切換到錯誤消息之前:

RAISERROR('Error',16,1) 
select top 1000 * from sys.objects so1,sys.objects so2,sys.objects so3 
WAITFOR DELAY '00:00:10' 

如果你想,如果發生錯誤的存儲過程提前退出,你必須及早擺脫困境。你可以重新編寫插入到是這樣的:

declare @cross_reference table (
     context varchar(20) not null 
    , value1  varchar(10) not null 
    , value2  varchar(10) not null 
) 

insert into @cross_reference (context,value1,value2) 
values ('map', 'from_value', 'to_value'), 
     ('map', 'from_value', 'to_value'), 
     ('map', 'from_value_xxxxx', 'to_value_xxxxxxx'); 
if @@ERROR !=0 or @@ROWCOUNT !=3 return 

或者,如果你不知道的行數,改變條件@@ROWCOUNT = 0

(或者,當然了,使用TRY/CATCH - 但我自己還沒有使用它們編寫太多的代碼,所以不能只是剔除一個例子)

您當前的代碼已經使每個插入獨立 - 所以那些插入可以工作,做和那些不能,產生錯誤信息。然後它繼續處理您的最終查詢。由於該表在左加入中使用,當然,對於最終查詢,表變量中是否存在任何行都無關緊要。

0

我無法完全重現您所描述的內容。有一件事我會說,專注於將數據插入表var,是因爲如果你有ANSI_WARNINGS ON,那麼它應該在插入點出錯。

SET ANSI_WARNINGS ON -- Gives the truncation error 
DECLARE @T1 TABLE (value1 varchar(10) not null) 
INSERT @T1 VALUES ('1234567890ABC') 

SET ANSI_WARNINGS OFF -- Does not give the truncation error. "1234567890" will be inserted 
DECLARE @T1 TABLE (value1 varchar(10) not null) 
INSERT @T1 VALUES ('1234567890ABC') 

你有ANSI_WARNINGS ON或OFF的連接?

+0

我試着用ANSI_WARNINGS明確地打開,但它的行爲方式完全相同。我在上面添加了更多細節。 – Ray

+0

在INSERT之後立即執行「SELECT * FROM @TableVar」來暫存內容?怎麼了?我有點難過,所以試圖建議我如何進行診斷。 – AdaTheDev