TSQL Арифметическое переполнение с использованием BIGINT - PullRequest
7 голосов
/ 16 февраля 2011

Может ли кто-нибудь уточнить для меня, почему я получаю сообщение об ошибке при попытке установить переменную @a в приведенном ниже примере?

DECLARE @a BIGINT
SET @a = 7*11*13*17*19*23*29*31
/*
ERROR:
Msg 8115, Level 16, State 2, Line 1
Arithmetic overflow error converting expression to data type int.
*/

Что я мог бы выяснить до сих пор, так это, внутренне, SQLначинает выполнять вычисления, вычисляя умножение и помещая временный результат в INT, затем преобразует его в BIGINT.

Однако, если я добавлю 1.0 * в мой список чисел, тамне является ошибкой, поэтому я считаю, что на этот раз SQL использует float как временный результат, а затем приводит его к BIGINT

DECLARE @b BIGINT
SET @b =   1.0  *  7*11*13*17*19*23*29*31
/*
NO ERROR
*/

Честно говоря, я не вижу ничего плохого в коде ... это такпросто ...

[Я использую SQL 2008]

[РЕДАКТИРОВАТЬ]

Спасибо Натану за ссылка .Это хорошая информация, о которой я не знал, но я все еще не понимаю, почему я получаю сообщение об ошибке и почему у меня есть «хитрости», чтобы заставить работать такой простой сценарий.

Это что-точто я должен знать, как иметь дело с программистом?

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

Ответы [ 2 ]

9 голосов
/ 16 февраля 2011

Когда вы выполняете подобные вычисления, отдельные числа сохраняются достаточно большими, чтобы содержать это число, то есть: число (1,0). Проверьте это:

Внимание! * * 1004 Когда вы используете +, -, *, / или% арифметических операторов к выполнять неявное или явное преобразование int, smallint, tinyint, или значения константы bigint к плавающие, действительные, десятичные или числовые данные типы, правила, которые SQL Server применяется, когда он рассчитывает данные тип и точность выражения результаты различаются в зависимости от того, запрос автопараметризован или нет.

Следовательно, похожие выражения в запросы могут иногда производить разные результаты. Когда запрос не автопараметрическое, постоянное значение сначала преобразуется в числовой, чей точность достаточно велика, чтобы держать значение константы, перед преобразование в указанный тип данных. Например, постоянное значение 1 преобразуется в числовое (1, 0), а постоянное значение 250 преобразуется в числовой (3, 0).

Когда запрос автоматически параметризован, постоянное значение всегда преобразуется в числовое (10, 0) перед преобразованием в окончательный тип данных. Когда / оператор не только может Точность типа результата отличается похожие запросы, но значение результата может отличаться также. Например, значение результата автопараметризации запрос, который включает в себя выражение ВЫБЕРИТЕ CAST (1.0 / 7 AS float) отличаются от значения результата тот же запрос, который не автопараметризованный, потому что результаты автопараметрического запроса будет усеченный, чтобы вписаться в числовой (10, 0) тип данных. Для дополнительной информации о параметризованных запросах см. Простая параметризация.

http://msdn.microsoft.com/en-us/library/ms187745.aspx


Редактировать

Это не ошибка в SQL Server. На этой же странице написано:

Тип данных int является основным целочисленным типом данных в SQL Server.

и

SQL Server автоматически не продвигает другие целочисленные типы данных (tinyint, smallint и int) в bigint.

Это определенное поведение. Как программист, если у вас есть основания полагать, что ваши данные будут переполнять тип данных, вы должны принять меры предосторожности, чтобы избежать такой ситуации. В этом случае простое преобразование одного из этих чисел в BIGINT решит проблему.

DECLARE @a BIGINT
SET @a = 7*11*13*17*19*23*29*CONVERT(BIGINT, 31)
5 голосов
/ 16 февраля 2011

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

Аналогично, вы можете сделать это:

DECLARE @a BIGINT,
        @b BIGINT

set @b = 1
SET @a = @b*7*11*13*17*19*23*29*31

Это отлично работаетпотому что он замечает, что есть BIGINT, поэтому он преобразует все INT в BIGINT, а затем выполняет умножение.

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