Ошибка преобразования при преобразовании значения varchar в int - PullRequest
8 голосов
/ 04 мая 2010

Microsoft SQL Server 2008 (SP1), получая неожиданную ошибку «Ошибка преобразования».

Не совсем уверен, как описать эту проблему, поэтому ниже приведен простой пример. CTE извлекает числовую часть определенных идентификаторов, используя условие поиска, чтобы гарантировать, что числовая часть действительно существует. CTE затем используется для нахождения наименьшего неиспользованного порядкового номера (вида):

CREATE TABLE IDs (ID CHAR(3) NOT NULL UNIQUE);

INSERT INTO IDs (ID) VALUES ('A01'), ('A02'), ('A04'), ('ERR');

WITH ValidIDs (ID, seq)
AS 
(
 SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
   FROM IDs 
  WHERE ID LIKE 'A[0-9][0-9]'
)
SELECT MIN(V1.seq) + 1 AS next_seq
  FROM ValidIDs AS V1
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM ValidIDs AS V2
                    WHERE V2.seq = V1.seq + 1
                  );

Ошибка: «Ошибка преобразования при преобразовании значения varchar 'RR' в тип данных int."

Я не могу понять, почему значение ID = 'ERR' следует рассматривать для преобразования, поскольку предикат ID LIKE 'A[0-9][0-9]' должен был удалить недопустимую строку из набора результатов.

Когда базовая таблица заменяется эквивалентным CTE, проблема исчезает, т.е.

WITH IDs (ID)
AS
(
 SELECT 'A01'
 UNION ALL 
 SELECT 'A02'
 UNION ALL 
 SELECT 'A04'
 UNION ALL 
 SELECT 'ERR' 
),
ValidIDs (ID, seq)
AS 
(
 SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
   FROM IDs 
  WHERE ID LIKE 'A[0-9][0-9]'
)
SELECT MIN(V1.seq) + 1 AS next_seq
  FROM ValidIDs AS V1
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM ValidIDs AS V2
                    WHERE V2.seq = V1.seq + 1
                  );

Почему базовая таблица вызывает эту ошибку? Это известная проблема?


UPDATE @sgmoore: нет, выполнение фильтрации в одном CTE и приведение в другом CTE все еще приводит к той же ошибке, например.

WITH FilteredIDs (ID)
AS 
(
 SELECT ID
   FROM IDs 
  WHERE ID LIKE 'A[0-9][0-9]'

), 
ValidIDs (ID, seq)
AS 
(
 SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
   FROM FilteredIDs 
)
SELECT MIN(V1.seq) + 1 AS next_seq
  FROM ValidIDs AS V1
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM ValidIDs AS V2
                    WHERE V2.seq = V1.seq + 1
                  );

Ответы [ 3 ]

4 голосов
/ 10 мая 2010

Это ошибка, о которой уже сообщалось как SQL Server не должен вызывать нелогичных ошибок (как я уже сказал, эту проблему трудно описать!) Эрланд Соммарског.

Ответ от команды по программированию SQL Server таков: «Проблема в том, что SQL Server выдает ошибки [слишком] охотно из-за нажатия предикатов / выражений во время выполнения запроса без учета логического результата запроса».

Я сейчас проголосовал за исправление, все делают то же самое, пожалуйста:)

0 голосов
/ 22 августа 2013

Это случилось со мной, потому что я сделал Union и не заботился о том, чтобы оба запроса имели поля в одинаковом порядке. Как только я это исправил, все было в порядке.

0 голосов
/ 04 мая 2010

Что делать, если вы замените раздел

SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM IDs 
WHERE ID LIKE 'A[0-9][0-9]'

С

SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM 
(
    select ID from IDs 
    WHERE ID LIKE 'A[0-9][0-9]'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...