Pov*_*vas 5 sql stored-procedures sql-server-2012
问题是:为什么在执行查询和存储过程时数据类型如何转换/解释会有区别?
我有一个存储过程,它给了我:
Msg 8115, Level 16, State 2, Procedure sp****ChargePackagingTest, Line 9
Arithmetic overflow error converting expression to data type nvarchar.
Run Code Online (Sandbox Code Playgroud)
问题是它只在作为存储过程执行时发生:
exec [sp****ChargePackagingTest] '2016-10-14', '2016-10-25'
Run Code Online (Sandbox Code Playgroud)
但是,如果我执行相同的查询(在存储过程外部复制并使用相同的参数声明并使用SQL管理工作室),我不会遇到问题.
最重要的是,我知道问题的确切位置:CONVERT(nvarchar(2),JobPDF.Pages/2)
存储过程说问题在第9行,但实际上并非如此.如果我将它更改为nvarchar(3),它甚至可以作为存储过程执行.
但是,JobPdf.Pages是可以为null的int类型:值只有24,48,72(我已经检查过).此外,它仅在有足够数据时崩溃,即,它不是特定于日期范围,而是特定于日期范围的长度.
存储过程代码:
ALTER PROCEDURE [dbo].[sp****ChargePackagingTest]
@dateFrom DateTime, @dateTo DateTime
AS
BEGIN
SELECT costPerOrder****.[Product Name], costPerOrder****.[Pack Price], SUM([Pack Count]) as [Pack Count], SUM(costPerOrder****.[Packaging Cost]) as [Packaging Cost]
FROM
(
-- Raw data aggregated by order
SELECT [Product Name], [Pack Price]
, CEILING(SUM(Quantity) * 1.0 / [Pack Items]) as [Pack Count] -- 1.0 converts it to decimal and uses decimal division
, CEILING(SUM(Quantity) * 1.0 / [Pack Items]) * [Pack Price] as [Packaging Cost]
FROM
(
-- Raw Polaroid data (basically we creating LookUp_Product and joining with orders)
select JobDetail.OrderId, ProductName + ' ' + CONVERT(nvarchar(2), JobPDF.Pages / 2) as [Product Name]
, job.Quantity
, CASE
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 24 THEN 0.063 -- **** 12 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 48 THEN 0.063 -- **** 24 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 72 THEN 0.089 -- **** 36 pages
ELSE NULL
END as [Pack Price]
,CASE
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 24 THEN 2 -- **** 12 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 48 THEN 2 -- **** 24 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 72 THEN 3 -- **** 36 pages
ELSE NULL
END as [Pack Items]
FROM Job WITH (NOLOCK)
inner join LookUp_Product WITH (NOLOCK) on LookUp_Product.ProductID = job.ProductID
inner join JobEvent WITH (NOLOCK) on JobEvent.JobID = job.JobID
inner join JobDetail WITH (NOLOCK) on JobDetail.JobID = job.JobID
inner join Orders WITH (NOLOCK) on Orders.OrderId = JobDetail.OrderID
inner join JobPDF WITH (NOLOCK) on JobPDF.JobID = job.JobID
where 1=1
AND LookUp_Product.ClientID = 'AC7EDBCD-39DF-45CE-8D96-A26EB17D1E2D'
AND Job.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A'
AND JobDetail.CurrentEventID = 999999
AND JobEvent.EventID = 999999
AND JobEvent.DateDone >= @dateFrom
AND JobEvent.DateDone < @dateTo
AND PackPrice is not null AND PackPrice <> 0.0000
) as Raw****Data
GROUP BY Raw****Data.OrderID, [Product Name], [Pack Price], [Pack Items]) costPerOrder****
GROUP BY [Product Name], [Pack Price]
ORDER BY [Product Name]
END
Run Code Online (Sandbox Code Playgroud)
查询执行示例:
declare @dateFrom DateTime = '2016-10-14'
declare @dateTo DateTime = '2016-10-25'
SELECT costPerOrder****.[Product Name], costPerOrder****.[Pack Price], SUM([Pack Count]) as [Pack Count], SUM(costPerOrder****.[Packaging Cost]) as [Packaging Cost]
FROM
(
-- Raw data aggregated by order
SELECT [Product Name], [Pack Price]
, CEILING(SUM(Quantity) * 1.0 / [Pack Items]) as [Pack Count] -- 1.0 converts it to decimal and uses decimal division
, CEILING(SUM(Quantity) * 1.0 / [Pack Items]) * [Pack Price] as [Packaging Cost]
FROM
(
-- Raw **** data (basically we creating LookUp_Product and joining with orders)
select JobDetail.OrderId, ProductName + ' ' + CONVERT(nvarchar(2), JobPDF.Pages / 2) as [Product Name]
, job.Quantity
, CASE
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 24 THEN 0.063 -- **** 12 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 48 THEN 0.063 -- **** 24 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 72 THEN 0.089 -- **** 36 pages
ELSE NULL
END as [Pack Price]
,CASE
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 24 THEN 2 -- **** 12 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 48 THEN 2 -- **** 24 pages
when LookUp_Product.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A' AND JobPDF.Pages = 72 THEN 3 -- ****36 pages
ELSE NULL
END as [Pack Items]
FROM Job WITH (NOLOCK)
inner join LookUp_Product WITH (NOLOCK) on LookUp_Product.ProductID = job.ProductID
inner join JobEvent WITH (NOLOCK) on JobEvent.JobID = job.JobID
inner join JobDetail WITH (NOLOCK) on JobDetail.JobID = job.JobID
inner join Orders WITH (NOLOCK) on Orders.OrderId = JobDetail.OrderID
inner join JobPDF WITH (NOLOCK) on JobPDF.JobID = job.JobID
where 1=1
AND LookUp_Product.ClientID = 'AC7EDBCD-39DF-45CE-8D96-A26EB17D1E2D'
AND Job.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A'
AND JobDetail.CurrentEventID = 999999
AND JobEvent.EventID = 999999
AND JobEvent.DateDone >= @dateFrom
AND JobEvent.DateDone < @dateTo
AND PackPrice is not null AND PackPrice <> 0.0000
) as Raw****dData
GROUP BY Raw****Data.OrderID, [Product Name], [Pack Price], [Pack Items]) costPerOrder****
GROUP BY [Product Name], [Pack Price]
ORDER BY [Product Name]
Run Code Online (Sandbox Code Playgroud)
我认为您的数据比您发现的要多。您是否distinct
对整个 JobPDF.Pages
专栏进行了测试,而不仅仅是“代表性”样本?
由于您的查询适用于某些日期范围,而不适用于其他日期范围,因此我建议采用不适用的范围并查看distinct
返回的值,arithmetic overflow
因为您的查询只能在除法之后返回超过 2 个字符。
下面的脚本说明了这一点,因为即使存在会导致失败的数据convert
,如果查询首先没有返回该数据,那么一切似乎都可以正常运行:
declare @a table (a int);
insert into @a values(7155),(72);
-- This query will run
select CONVERT(nvarchar(2), a / 2)
from @a
where a < 100;
-- This query will not
select CONVERT(nvarchar(2), a / 2)
from @a;
Run Code Online (Sandbox Code Playgroud)
很简单,我不明白为什么会有除上述之外的任何问题。您能否运行以下命令并将输出添加到您的问题中?如果日期与产生错误的范围不相关,请将这些日期替换为以下内容:
select distinct JobPDF.Pages
FROM Job WITH (NOLOCK)
inner join LookUp_Product WITH (NOLOCK) on LookUp_Product.ProductID = job.ProductID
inner join JobEvent WITH (NOLOCK) on JobEvent.JobID = job.JobID
inner join JobDetail WITH (NOLOCK) on JobDetail.JobID = job.JobID
inner join Orders WITH (NOLOCK) on Orders.OrderId = JobDetail.OrderID
inner join JobPDF WITH (NOLOCK) on JobPDF.JobID = job.JobID
where 1=1
AND LookUp_Product.ClientID = 'AC7EDBCD-39DF-45CE-8D96-A26EB17D1E2D'
AND Job.ProductID = 'AA5DF53B-4B58-4298-AFA3-EE856610689A'
AND JobDetail.CurrentEventID = 999999
AND JobEvent.EventID = 999999
AND JobEvent.DateDone >= '20161014'
AND JobEvent.DateDone < '20161025'
AND PackPrice is not null AND PackPrice <> 0.0000
Run Code Online (Sandbox Code Playgroud)