43

varcharUserIDをに変換することに行き詰まっていますINTUserIDこのコラムが最初に INT として作成されなかった理由を聞かないでください。長い話です。

だから私はこれを試しましたが、うまくいきません。エラーが表示されます:

select CAST(userID AS int) from audit

エラー:

varchar 値 '1581 の変換時に変換に失敗しました................................................................. ................................................................... ....................................' をデータ型 int に変換します。

私がやったselect len(userID) from auditところ、スペースではない128文字が返されました。

ID番号とASCII値= 0の後に続くASCII文字を検出しようとしました。

LTRIMRTRIM、および に置き換えchar(0)てみまし''たが、機能しません。

以下のように固定文字数を伝える場合にのみ機能しますが、UserID常に4文字であるとは限りません。

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

5 に答える 5

23

テーブルを更新して、これらの文字を取り除くことができます。

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) の 6 つのインスタンスが続きます。そして、私が投稿した回避策は間違いなく機能します:

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)ん。

あなたがそれを聞きたくないのはわかっていますが、これが人々にとって苦痛であることを本当にうれしく思います。なぜなら、人々がデータ型について非常に悪い決定を下したときに、反論する戦争の話が増えているからです.

于 2013-04-12T18:06:09.410 に答える
3

これは、元のポスターよりも、結果を探している人向けです。これは私のために働いた...

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
于 2016-04-06T16:23:53.367 に答える
2

数値をトリミングして、何が得られるかを確認します。

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

それが正しい値を返す場合は、次のようにします。

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

それが正しい値を返さない場合は、空のスペースを削除するために置換を行います。

 select convert(int, replace(userid, char(0), '')) from audit
于 2013-04-12T18:07:00.790 に答える