2015-04-02 68 views
-1

我們有一些在過去一天開始拋出錯誤的代碼。該代碼幾個月沒有改變。該錯誤消息是:無理由的SQL截斷錯誤

消息8152,級別16,狀態2
字符串或二進制數據將被截斷。

的SQL語句是:

UPDATE TUP 
SET insured_state_cd = UTCA.state_province_cd 
FROM #TEMP_UAFR_POLICY TUP 
    JOIN dbo.UVW_THIRDS UT ON 
     TUP.prim_owner_third_id = UT.third_id 
    JOIN dbo.UVW_THIRDS_CONTACTS_ADDRESSES UTCA ON 
     UT.primary_address_id = UTCA.address_id 
    JOIN dbo.UVW_INTERNATIONAL_COUNTRY UIC ON 
     UTCA.country_cd = UIC.country_cd 

現在,我會告訴你,是的,UTCA.state_province_cd列比insured_state_cd列大。我們知道這不是一件好事,但我們的測試過程至少需要一個月的時間才能將變更批准並投入生產。我們真的需要弄清楚這個問題的原因。

我們檢查了UTCA表,沒有記錄的長度超過2,這是TUP表中列的大小。由於它是CHAR類型,我們還檢查了表的二進制值以確保它不是回車或其他隱藏字符。

爲了增加神祕感,此代碼的工作:

UPDATE TUP 
SET insured_state_cd = UTCA.state_province_cd 
FROM #TEMP_UAFR_POLICY TUP 
    JOIN dbo.UVW_THIRDS UT ON 
     TUP.prim_owner_third_id = UT.third_id 
    JOIN dbo.UVW_THIRDS_CONTACTS_ADDRESSES UTCA ON 
     UT.primary_address_id = UTCA.address_id 
    JOIN dbo.UVW_INTERNATIONAL_COUNTRY UIC ON 
     UTCA.country_cd = UIC.country_cd 
WHERE UTCA.state_province_cd IN 
      (SELECT DISTINCT UTCA2.state_province_cd 
      FROM dbo.UVW_THIRDS_CONTACTS_ADDRESSES UTCA2) 

正如你所看到的,第二個代碼是一樣的,第一,它基本上只是檢查做1 = 1?此外,代碼以原始形式在我們的開發服務器上運行。我們直接備份數據庫,恢復到開發,運行代碼,它的工作原理。

+0

如果你只想要UTCA.state_province_cd的前兩個字符,那'SET insured_state_cd = LEFT(UTCA.state_province_cd,2)...'''開發人員和生產數據庫是否運行*完全相同版本的SQL Server? – 2015-04-02 18:28:17

+1

下面是一個*瘋狂的想法 - 爲什麼不創建#temp表,以便其列和數據類型實際上匹配源表?我無法理解爲什麼增加#temp表定義的長度需要任何時間來批准和部署。如果這需要一個月,那麼你有更大的問題,字符串截斷。 – 2015-04-02 18:57:10

+1

另外,你是否檢查了連接產生的值,或者表中的所有***值? SQL Server可以按照不同的順序優化事物,其中在一個服務器上的過濾器之前檢查長度,並且在另一個過濾器之後檢查長度。 – 2015-04-02 18:59:35

回答

1

我的猜測是你用LEN(列)來檢查數據?這將告訴你字符的數量,不包括任何空格。我有一種感覺,那就是空白爲什麼會出錯。嘗試修剪白色空間。

UPDATE TUP 
SET insured_state_cd = RTRIM(LTRIM(UTCA.state_province_cd)) 
FROM #TEMP_UAFR_POLICY TUP 
    JOIN dbo.UVW_THIRDS UT ON 
     TUP.prim_owner_third_id = UT.third_id 
    JOIN dbo.UVW_THIRDS_CONTACTS_ADDRESSES UTCA ON 
     UT.primary_address_id = UTCA.address_id 
    JOIN dbo.UVW_INTERNATIONAL_COUNTRY UIC ON 
     UTCA.country_cd = UIC.country_c 
+0

當然,它可以通過使不幸的是,由於瘋狂的代碼更改過程,字段長度匹配或修剪,直到發佈後我才能更改。這個過程很好地工作了很多年,並在過去的一天剛剛打破。就模式或設置而言,沒有任何變化,顯然數據總是在變化,但在我正在使用的時間範圍內沒有其他變化。 – Kevin 2015-04-02 19:33:18

+0

您是否嘗試過SELECT UTCA.state_province_cd FROM UTCA WHERE DATALENGTH(CAST(UTCA.state_province_cd AS VARCHAR(5))> 2?是否返回任何內容? – Stephan 2015-04-02 20:05:06

0

你說什麼都沒有引發任何紅旗或對我有明顯的答案。這裏有一些我會研究的東西(你可能已經完成了)。

你說「CHAR」類型。 CHAR或VARCHAR?讓我們想知道領先和/或尾隨空格。 (那裏有任何nvarchars?怎麼樣varchar(max)?)它有助於查看#TEMP_UAFR_POLICY和UVW_THIRDS_CONTACTS_ADDRESSES的表定義。

您已經使用了LEN() DATALENGTH()函數來檢查列,是嗎?

「支持生產並在開發中恢復」與#tempdbs結合使我想起我們安裝了SQL代碼頁(或其他)與我們其他所有SQL安裝不同的。數據庫都是一樣的,但系統數據庫(最值得注意的是tempdb)是在不同的假設下運行的,並且導致了一些相當微妙的問題。也許有什麼事情在那裏?

在兩種環境之間檢查並比較SQL的服務包的版本和版本。

+0

好主意,但不幸的是我在這裏沒有找到任何東西。 2)和char(5),由於它們是CHAR,它們總是返回一個datalength =字段的長度,我檢查了tempdb,它具有相同的設置,包括兩臺服務器上的排序規則。 – Kevin 2015-04-02 19:30:58