SQL 标量值函数

Posted

技术标签:

【中文标题】SQL 标量值函数【英文标题】:SQL Scalar-Valued Function 【发布时间】:2019-03-14 18:08:56 【问题描述】:

我希望根据作为函数参数提供的 Studio 检索利润值 (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.

任何帮助将不胜感激!

【问题讨论】:

返回是int 数据类型。尝试声明一个变量以将SUM() 首先放入,然后返回该变量。 FilmBoxOfficeDollarFilmBudgetDollars 是否都是数据类型 int 实际上仔细观察,您需要在RETURNS int 之后和BEGIN 之前添加一个AS @WEI_DBA 感谢您的回复!是的,FilmBoxOfficeDollarsFilmBudgetDollars 都是 int 数据类型。我现在还添加了AS @WEI_DBA 我尝试使用DECLARE 设置变量,然后将SET it = 设置为FilmBoxOfficeDollars - 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."

但是,帮自己一个忙,改用视图。像这样的标量对于报表的性能来说是很糟糕的。除非标量函数只是根据输入值进行计算(即不触及底层的持久数据),否则不应使用标量函数。

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 数据类型相关的 reading。具体来说,integer datatypes。

【讨论】:

【参考方案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 来增加您的返回类型范围。

【讨论】:

以上是关于SQL 标量值函数的主要内容,如果未能解决你的问题,请参考以下文章

sql [sql]标量值函数示例

为啥 SQL Server 标量值函数变慢?

具有嵌套 CASES 的 Sql 标量值函数

sql标量值函数非常慢

sql中的表值函数与标量值函数区别与用法

在 SQL Server 中计算 GS1 校验位的标量值函数