SQL Server - простой выбор и преобразование между int и строкой - PullRequest
0 голосов
/ 11 июля 2011

У меня есть простое выражение выбора, как это:

SELECT [dok__Dokument].[dok_Id], 
       [dok__Dokument].[dok_WartUsNetto], 
       [dok__Dokument].[dok_WartUsBrutto], 
       [dok__Dokument].[dok_WartTwNetto], 
       [dok__Dokument].[dok_WartTwBrutto], 
       [dok__Dokument].[dok_WartNetto], 
       [dok__Dokument].[dok_WartVat], 
       [dok__Dokument].[dok_WartBrutto], 
       [dok__Dokument].[dok_KwWartosc] 
  FROM [dok__Dokument] 
 WHERE [dok_NrPelnyOryg] = 2753 
   AND [dok_PlatnikId] = 174 
   AND [dok_OdbiorcaId] = 174 
   AND [dok_PlatnikAdreshId] = 625 
   AND [dok_OdbiorcaAdreshId] = 624

Столбец dok_NrPelnyOryg относится к типу varchar (30) и не является нулевым.

Таблица содержала как целочисленные, так и строковые значения в этом столбце, и этот оператор select был запущен миллионы раз.

Однако недавно это начало сбой с сообщением:

Преобразование не удалось при преобразовании значения varchar 'garbi czerwiec B' в тип данных int.

Небольшое объяснение: таблица содержит несколько записей «документа», а упомянутый столбец содержит номер оригинала документа (который поступает из нескольких разных источников).

Я знаю, что могу это исправить, добавив '' вокруг числа, но я скорее ищу объяснение, почему это работало, и теперь, когда ничего не менялось, оно падает.

Ответы [ 3 ]

2 голосов
/ 11 июля 2011

Возможно, что изменение плана (из-за изменения статистики, перекомпиляции и т. Д.) Привело к тому, что эти данные были оценены ранее (например, полное сканирование), или что эти конкретные данные не были в таблице ранее (возможно, до того, как это начало происходить,там не было плохих данных).Если предполагается, что это число, то сделайте его числовым столбцом.Если он также должен разрешать строки, тогда прекратите рассматривать его как число.Если вы правильно параметризуете свои утверждения и всегда передаете varchar, вам не нужно беспокоиться о том, заключено ли значение в одинарные кавычки.

1 голос
/ 11 июля 2011

Все эти операции сравнения равенства подчиняются правилам Тип данных SQL Server:

Когда оператор объединяет два выражения разных типов данных, правила для данныхТип приоритета указывает, что тип данных с более низким приоритетом преобразуется в тип данных с более высоким приоритетом.

Поскольку типы символов имеют более низкий приоритет, чем типы int, запрос в основном такой же, как:

SELECT ...
  FROM [dok__Dokument] 
 WHERE cast([dok_NrPelnyOryg] as int) = 2753
  ...

Это имеет два эффекта:

  • делает все индексы столбцов, включенных в предложение WHERE бесполезными
  • , это может вызвать ошибки преобразования.

Вы не первый, у кого возникла эта проблема, на самом деле, в нескольких случаях CSS, с которыми я столкнулся, я в итоге написал статью об этом: На логическом операторе SQL Server короткое замыкание .

Правильное решение вашей проблемы состоит в том, что , если значение поля числовое, тогда тип столбца должен быть числовым .поскольку вы говорите, что данные поступают из стороннего приложения 3 rd , которое вы не можете изменить, лучшее решение - отказаться от поставщика этого приложения и выбрать приложение, которое знает, что делает.Если не считать этого, вам нужно искать типы символов в символьных столбцах:

SELECT ...
  FROM [dok__Dokument] 
 WHERE [dok_NrPelnyOryg] = '2753'
  ...

В языке AD. Управляемого ADO.Net это означает, что вы используете SqlCommand следующим образом:

SqlCommand cmd = new SqlCommand (@"    SELECT ...
      FROM [dok__Dokument] 
     WHERE [dok_NrPelnyOryg] = @nrPelnyOryg
      ... ");
cmd.Parameters.Add("@nrPelnyOryg", SqlDbType.Varchar).Value = "2754";
...

Просто убедитесь, что вы не попадаете в его ловушку для передачи параметра NVARCHAR (Unicode) для сравнения со столбцом VARCHAR, так как те же самые правила приоритета типов данных, приведенные ранее, приведут к тому, что сравнение произойдет для типа NVARCHAR, таким образом рендерингиндексы, опять же, бесполезны.Самый простой способ попасть в эту ловушку - использовать dredded AddWithValue и передать строковое значение.

0 голосов
/ 11 июля 2011

Ваш запрос перестал работать, потому что кто-то вставил текстовую строку в поле, которое вы запрашиваете, используя INT.До этого времени можно было неявно преобразовывать данные, но теперь это уже не так.

Я бы проверил ваши данные и, что более важно, модель;как сказал Аарон, вам нужно разрешить строки в этом поле?Если нет, измените тип данных, чтобы предотвратить это в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...