2013-04-12 192 views
21

我一直在將varcharUserID轉換爲INT。我知道,請不要問爲什麼這個UserID列最初並不是以INT的形式創建的,長話短說。SQL Server:將varchar轉換爲INT

所以我試過這個,但它不起作用。並給我一個錯誤:

select CAST(userID AS int) from audit 

錯誤:

Conversion failed when converting the varchar value '1581............................................................................................................................' to data type int.

我做select len(userID) from audit並返回128個字符,這不是空格。

我試圖檢測ASCII字符的那些ID號和ASCII值後尾隨= 0

更新!!!

我也試過LTRIM,RTRIM,並用''代替char(0),但不起作用。

當我告訴固定的字符數如下所示時,它唯一的工作方式是這樣,但UserID並不總是4個字符。

select CAST(LEFT(userID, 4) AS int) from audit 

感謝,

+0

在表中的用戶ID列只有整數值或VARCHAR值。對於如:122像這樣或122Adf這樣......? – Pandian

+0

UserID列只有Integer值。謝謝! – Milacay

回答

16

你可以嘗試更新表來擺脫這些字符:

UPDATE dbo.[audit] 
    SET UserID = REPLACE(UserID, CHAR(0), '') 
    WHERE CHARINDEX(CHAR(0), UserID) > 0; 

但你還需要解決什麼是把這個壞數據進入表在第一個地方。在此期間也許嘗試:

SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) 
    FROM dbo.[audit]; 

但是,這並不是一個長期的解決方案。修復數據(以及數據類型)。如果不能立即修復的數據類型,那麼你可以迅速地通過增加一個檢查約束找到罪魁禍首:

ALTER TABLE dbo.[audit] 
    ADD CONSTRAINT do_not_allow_stupid_data 
    CHECK (CHARINDEX(CHAR(0), UserID) = 0); 

編輯

好了,這是絕對是一個4位數的整數,其後由CHAR的六個實例(0)。我貼絕對是替代方法適用於我:

DECLARE @foo TABLE(UserID VARCHAR(32)); 
INSERT @foo SELECT 0x31353831000000000000; 

-- this succeeds: 
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM @foo; 

-- this fails: 
SELECT CONVERT(INT, UserID) FROM @foo; 

請確認自身的代碼(很好,第一SELECT,反正)你的作品。如果確實如此,那麼您得到的錯誤來自不同行中的另一個非數字字符(如果不存在,那麼可能您的構建中某個特定的錯誤尚未修復)。嘗試縮小它,你可以通過下列字符組成的查詢採取隨機值,然後循環:

SELECT UserID, CONVERT(VARBINARY(32), UserID) 
    FROM dbo.[audit] 
    WHERE UserID LIKE '%[^0-9]%'; 

於是採取隨機排,然後將輸出粘貼到這樣的查詢:

DECLARE @x VARCHAR(32), @i INT; 
SET @x = CONVERT(VARCHAR(32), 0x...); -- paste the value here 
SET @i = 1; 
WHILE @i <= LEN(@x) 
BEGIN 
    PRINT RTRIM(@i) + ' = ' + RTRIM(ASCII(SUBSTRING(@x, @i, 1))) 
    SET @i = @i + 1; 
END 

你遇到一排一些其他原因,而不是CHAR(0)失敗之前這可能需要一些試驗和錯誤 - 因爲你不能真正篩選出含有CHAR(0)行,因爲它們可能含有CHAR(0)CHAR(something else)。我們都知道你有一個像在表中的值:

SELECT '15' + CHAR(9) + '23' + CHAR(0); 

...這也不能轉換爲整數,您是否已經更換CHAR(0)與否。

我知道你不想聽到它,但我真的很高興這對人們來說是痛苦的,因爲現在當人們對數據類型做出非常差的決定時,他們有更多的戰爭故事可以推遲。

+0

我試過「SELECT CONVERT(INT,REPLACE(UserID,CHAR(0),'')) FROM dbo。[audit];」,但它不起作用。我也試過LTRIM和RTRIM,但也不管用......感謝您的幫助 – Milacay

+0

@Milacay,您確定'CHAR(0)'是列中的* only *無效值嗎?請確定一行失敗,然後告訴我們輸出,例如:'SELECT CONVERT(VARBINARY(32),UserID)FROM dbo。[audit] WHERE LEFT(UserID,4)='1581';' –

+0

我用「varbinary(32)...」運行你的查詢,輸出是:0x31353831000000000000。順便說一句,此varchar字段(userID)從Varbinary(128)轉換爲Varchar(128),現在我想將其轉換爲INT以加入不同表格上的用戶ID ...謝謝@Aaron – Milacay

0

我會嘗試修邊數,看看你會得到什麼:

select len(rtrim(ltrim(userid))) from audit 

如果返回正確的值,那麼就去做:

select convert(int, rtrim(ltrim(userid))) from audit 

如果不返回正確的值,然後我會做一個替換刪除空的空間:

select convert(int, replace(userid, char(0), '')) from audit 
+0

我嘗試了所有LTRIM,RTRIM,並用''替換char(0),但也不起作用。奇怪的!謝謝。 – Milacay

14

此問題已獲得91,000次瀏覽也許很多人都在尋找一個更通用的解決問題的標題是「錯誤的varchar轉換爲INT」

如果你是SQL Server上處理這種無效數據2012+的一種方法是使用TRY_CAST

SELECT TRY_CAST (userID AS INT) 
FROM audit 

在以前的版本中,你可以使用

SELECT CASE 
     WHEN ISNUMERIC(RTRIM(userID) + '.0e0') = 1 
       AND LEN(userID) <= 11 
      THEN CAST(userID AS INT) 
     END 
FROM audit 

兩個返回NULL如果該值不能被轉換。

在具體的情況下,你有你的問題與已知的不良值,但我會使用以下。

CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT) 

試圖替換空字符通常是有問題的,除非使用二進制排序規則。

+0

請解釋爲什麼添加.0e0使其成爲數字? – Tigran

+1

@Tigran它不會使其數字。追加這有助於驗證已經是數字的字符串是否是整數。例如。當寫成123.0e0時'123'會通過,但'123.45'將失敗,因爲'123.45.0e0'無效。 –

1

這是更多的人搜索結果,比原來的後呃。這個工作對我來說...

declare @value varchar(max) = 'sad'; 
select sum(cast(iif(isnumeric(@value) = 1, @value, 0) as bigint)); 

returns 0 

declare @value varchar(max) = '3'; 
select sum(cast(iif(isnumeric(@value) = 1, @value, 0) as bigint)); 

returns 3