#sql-server #tsql #parameters #user-defined-functions
#sql-сервер #tsql #параметры #определяемые пользователем функции
Вопрос:
Я пытаюсь получить значение прибыли (FilmBoxOfficeDollar — FilmBudgetDollars) на основе студии, указанной в качестве параметра функции.
USE Movies;
GO
CREATE FUNCTION fnmovieProfits(@StudioName nvarchar(255))
RETURNS int
AS
BEGIN
RETURN (SELECT SUM(FilmBoxOfficeDollars - FilmBudgetDollars)
FROM Film JOIN Studio
ON Film.FilmStudioID = Studio.StudioID
WHERE StudioName = @StudioName);
END;
GO
SELECT [dbo].[fnmovieProfits]('Dreamworks');
Всякий раз, когда я запускаю это, чтобы извлечь часть данных, я получаю следующую ошибку:
Msg 8115, Level 16, State 2, Line 13
Arithmetic overflow error converting expression to data type int.
Буду признателен за любую помощь!
Комментарии:
1. Возвращаемый параметр представляет собой
int
тип данных. Попробуйте объявить переменную, чтобы сначала поместитьSUM()
в нее, а затем вернуть переменную. Является лиFilmBoxOfficeDollar
иFilmBudgetDollars
оба типа данныхint
?2. На самом деле, при ближайшем рассмотрении вам нужно
AS
послеRETURNS int
и передBEGIN
.3. @WEI_DBA Спасибо за отзыв! Да, оба
FilmBoxOfficeDollars
иFilmBudgetDollars
являютсяint
типами данных. Я также добавилAS
now.4. @WEI_DBA Я пытался использовать
DECLARE
для установки переменной, а затемSET
it = toFilmBoxOfficeDollars - FilmBudgetDollars
но по какой-то причине получаю сообщение об ошибке. Есть идеи?
Ответ №1:
Проблема, с которой вы сталкиваетесь, заключается в том, что вы превышаете допустимое значение 32-разрядного числа (INT); если вы приведете / преобразуете в 64-разрядное число (BIGINT) и вернете этот тип данных, проблема будет исправлена. Доказательство концепции, показывающее проблему:
DECLARE @BigNumber INT=2000000000
select CONVERT(BIGINT,@BigNumber) CONVERT(BIGINT,@BigNumber) --returns 4,000,000,000
select (@BigNumber @BigNumber) --errors with "Arithmetic overflow error converting expression to data type int."
НО сделайте себе одолжение и используйте вместо этого view. Подобные скаляры ужасно влияют на производительность отчетов. Скалярные функции никогда не следует использовать, если они просто не выполняют вычисления на основе входных значений (т. Е. Не затрагивают базовые, сохраненные данные).
CREATE VIEW dbo.v_StudioProfits
AS
SELECT
StudioName,
SUM(CONVERT(BIGINT,FilmBoxOfficeDollars) - CONVERT(BIGINT,FilmBudgetDollars)) AS [Profit]
FROM Film
INNER JOIN Studio ON Film.FilmStudioID = Studio.StudioID
GROUP BY StudioName
GO
SELECT * FROM dbo.v_StudioProfits WHERE StudioName='Dreamworks'
Соответствующее чтение типов данных SQL Server. В частности, целочисленные типы данных.
Ответ №2:
Ваша сумма превышает int
диапазон. Вы должны определить возвращаемый тип как bigint
:
CREATE FUNCTION fnmovieProfits(@StudioName nvarchar(255))
RETURNS bigint
AS.......
Максимальное значение, которое вы можете вернуть с int
типом возвращаемого значения, является 2147483647
. Ваш sum
, вероятно, больше этого.
Один из примеров функции, которая превышает возвращаемый тип:
CREATE FUNCTION testFunction()
RETURNS int
AS
BEGIN
RETURN (SELECT 2147483647 1);
END;
GO
SELECT [dbo].[testFunction]();
При ее выполнении вы получите следующую ошибку:
Msg 8115, Level 16, State 2, Line 8
Arithmetic overflow error converting expression to data type int.
Таким образом, решение состоит в том, чтобы просто увеличить диапазон возвращаемых типов, заменив int
на bigint
.