Ошибка среды SQL Server Management Studio при преобразовании несуществующей строки

#sql #sql-server #tsql #type-conversion #numeric

Вопрос:

У меня есть таблица со varchar столбцом, в котором есть какие-либо значения. Я хотел отфильтровать только числовые значения и сравнить их с другими числами. Но я всегда получаю:

Ошибка преобразования значения varchar «!=»)» в тип данных int

Но !=») там даже не существует

Сначала я подумал, что это может быть там, и просто проверил все требования, даже если числовая проверка уже не удалась. Поэтому я поместил это в подзапрос. Но ошибка все равно случается.

Это мой вопрос:

 SELECT CAST(data AS float) 
FROM
    (SELECT DISTINCT Data 
     FROM [dbo].[log] 
     WHERE [Time]>='2021-08-04 00:00:00.000' 
       AND ISNUMERIC(data) = 1 
       AND Data NOT LIKE '%[^(0-9-.)]%'
    ) AS t
WHERE 
    data > 50
 

Есть какие-нибудь идеи?

Комментарии:

1. SQL Server не обязан обрабатывать предложения в том порядке, в котором вы думаете; data>50 их можно легко проанализировать до ISNUMERIC(data) = 1 или Data NOT LIKE '%[^(0-9-.)]%' . Я бы предложил удалить эти 2 пункта и просто использовать TRY_CONVERT(int, data) > 50 . Или, еще лучше, прекратите хранить числовые данные в varchar

2. Ну, это не моя база данных, я должен работать с тем, что я получаю. Я предположил, что исправлю одно из положений, как только обнаружу проблему. Просто попробовал TRY_CONVERT(float, data) IS NOT NULL вместо этого, но это привело к той же ошибке.

3. Я понимаю, что подзапрос обрабатывается в ожидаемом порядке. Я бы поспорил ISNUMERIC , что функция иногда возвращает значения, которые не являются действительными числами, например точки и запятые. Из-за того, что вы не конвертируете Data число в свой подзапрос, это может привести к проблемам в фильтре data > 50

4. Невозможно TRY_CONVERT(float, data) IS NOT NULL вернуть эту ошибку, @JaimeDrq . Предположительно, вы все еще оставили некоторые неявные преобразования в своем запросе.

5. Спасибо @Larnu, я сделал несколько тестов, и вы совершенно правы

Ответ №1:

Вы могли бы использовать TRY_CAST для получения NULL неверных входных данных — вместо исключения. ISNUMERIC общеизвестно, что он плохо определяет, действительно ли значение столбца числовое — или нет…..

 SELECT 
    NumericData
FROM
    (SELECT DISTINCT 
         Data,
         NumericData = TRY_CAST(data AS float) 
     FROM 
         [dbo].[log] 
     WHERE 
         [Time]>='2021-08-04 00:00:00.000' 
         AND Data NOT LIKE '%[^(0-9-.)]%') AS t
WHERE 
    t.NumericData > 50
 

и вы могли бы найти оскорбительные данные, используя:

 SELECT 
    data,
    NumericData = TRY_CAST(data AS float) 
FROM
    (SELECT DISTINCT Data 
     FROM [dbo].[log] 
     WHERE [Time]>='2021-08-04 00:00:00.000' 
       AND Data NOT LIKE '%[^(0-9-.)]%') AS t
WHERE 
    TRY_CAST(data AS float) IS NULL
 

Комментарии:

1. Спасибо, запрос работает. Но неправильный запрос данных не дает никаких результатов. Но, как я уже сказал, его даже нет в таблице.

Ответ №2:

TRY_CAST() (или аналогичная функция, безусловно, является правильным подходом. Я хочу отметить, что вы можете упростить свой запрос:

 SELECT DISTINCT TRY_CAST(data AS float)  
 FROM [dbo].[log] 
 WHERE [Time] >= '2021-08-04' AND
       TRY_CAST(data AS float) > 50;
 

Вам не нужен компонент времени для сравнения времени. Вам не нужно использовать LIKE , потому TRY_CAST() что делает это за вас.

Комментарии:

1. Да LIKE , это был просто подход, чтобы получить только цифры. Достаточно одного метода.. пока это доставляет то, что я хочу.