我有一个复杂的数据视图,以递归方式链接和汇总信息。
每晚计划任务运行一个存储过程,该存储过程从数据视图中选择所有数据,并将其插入表中,以便用户可以比在数据视图上运行select语句更快地查询和分析数据
父表包含几十万条记录,导出的结果集大小超过1,000,000条记录。
对于大多数夜晚来说,导出过程没有任何问题,但是,如果用户在我们的主ERP系统中输入了错误的值,它将使夜间进程崩溃,因为其中一个十进制字段将包含一个不适合的值在我必须对数据进行的一些转换中。调试和查找特定的错误字段可能非常困难且耗时。
话虽如此,我已经阅读了两个SQL设置NUMERIC_ROUNDABORT
和ARITHABORT
。这听起来像是解决我的问题的完美选择,但是,我似乎无法使用我的数据视图或存储过程。
我的存储过程只不过是一个TRUNCATE和INSERT语句。我附上......
SET NUMERIC_ROUNDABORT OFF
SET ARITHABORT OFF
...到SP的开头并没有帮助。我认为这是因为技术上错误发生在与数据视图相关的代码中。
接下来,我尝试将两个扩展属性添加到数据视图,希望这可以工作。它没有。
有没有办法可以设置这些SQL属性来忽略舍入错误,以便我可以从数据视图中导出数据?
我知道对于我们大多数人来说,作为回答者,我们的第一个倾向是要求代码。然而,在这种情况下,代码非常复杂和专有。我知道修复导致偶尔溢出的定义是最理想的解决方案,但在这种情况下,忽略这些类型的错误要高效得多,因为它们发生在如此罕见的基础上并且很难排除故障。
我该怎么做才能忽略这种行为?
更新
偶然的机会,我相信我可能已找到问题的根本原因,但是,我不知道为什么会发生这种情况。从那时起它就没有了。
通过我的表视图,我有各种计算字段。由于这些字段需要适合表中定义为decimal (12, 5)
的字段,因此我始终将视图字段语句包装在CAST( ... AS DECIMAL(12, 5))
子句中。
偶然的机会,我偶然发现了一个奇怪的事。我决定看看SSMS如何“看到”我的数据视图。在SSMS对象资源管理器中,我展开了Views-> [My View] -Columns部分,我看到其中一个字段被定义为decimal (13, 5)
。
我认为我必须在我的某个演员语句中犯了一个错误,但是在遍历表格视图的代码之后,没有decimal(13, 5)
字段的定义?!我唯一的猜测是SSMS看到的视图字段的定义必须从结果数据中导出。但是,我不清楚这是怎么发生的,因为我将每个字段都改为decimal(12, 5)
。
我想知道为什么会这样,但是,我的原始问题仍然存在。如何以及在表视图中定义什么SET语句将忽略所有算术溢出并在具有错误数据的字段中写入空值?
最终评论
我已经将HeavenCore的回答标记为答案,因为它确实解决了我的问题,但它没有解决我的根本问题。
经过一些故障排除并试图让我的出口工作后,我将不得不尝试不同的方法。即使我将NUMERIC_ROUNDABORT
和ARITHABORT
属性设置为OFF
,我仍然无法让导出工作。
答案 0 :(得分:4)
我认为ARITHABORT
是你的朋友。
例如,使用SET ARITHABORT OFF
& SET ANSI_WARNINGS OFF
将使其无法投射的值为NULL(而不是抛出异常)
这是一个简单的例子:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_OverflowExample](
[Value] [decimal](12, 2) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[tbl_OverflowExample] ([Value]) VALUES (CAST(9999999999.00 AS Decimal(12, 2)))
GO
INSERT [dbo].[tbl_OverflowExample] ([Value]) VALUES (CAST(1.10 AS Decimal(12, 2)))
GO
--#### Select data without any casting - works
SELECT VALUE
FROM dbo.tbl_OverflowExample
--#### With ARITHABORT and ANSI warnings disabled - Returns NULL for 999999 but 1.10 as expected
SET ARITHABORT OFF;
SET ANSI_WARNINGS OFF;
SELECT CONVERT(DECIMAL(3, 2), VALUE)
FROM dbo.tbl_OverflowExample
GO
--#### With defaults - Fails with overflow exception
SET ARITHABORT ON;
SET ANSI_WARNINGS ON;
SELECT CONVERT(DECIMAL(2, 2), VALUE)
FROM dbo.tbl_OverflowExample
就个人而言 - 如果底层值大于目标数据类型,我更喜欢调试视图并使用一些CASE /.../ END
语句返回NULL
- 这将确保视图无论连接选项。
编辑:纠正了一些事实错误