【问题标题】:How to set decimal precision dynamically using a variable如何使用变量动态设置小数精度
【发布时间】:2020-09-09 13:41:38
【问题描述】:

我正在尝试在如下所示的存储过程中动态设置小数精度

 DECLARE @precison int
 select @precison = [ConfigValue] from [TestData] WHERE ConfigName = 'Precision'
 select CAST( (10.56/10.25)as decimal(18, @precision))

如果精度为“2”,SP 应返回“1.03”作为结果。但强制转换函数不接受 @precision 参数作为变量。我想从存储过程中以十进制本身返回数据。我如何在 SQL Server 中实现这一点

【问题讨论】:

  • 你首先想做什么?该值将返回给精度并不重要的客户端。您是否尝试截断或舍入结果?
  • 你不能,不是没有动态SQL;然后变量将仅在动态语句内具有范围。然而,这闻起来像 XY Problem
  • 至于为什么不能改变精度,SQL或多或少是一种强类型语言。类型和精度非常重要,因为它们可能导致数据丢失或意外截断。查询引擎必须能够验证查询不会执行无效操作,这在不知道类型大小的情况下是不可能的
  • "如果格式化数据通过SP发送会更好" 不,反之亦然。格式化是由表示层来做的,而不是 RDBMS。这就是为什么它被称为 presentation 层;它正在确定如何最好地将数据呈现给最终用户。

标签: sql sql-server database reporting-services decimal


【解决方案1】:

这里的问题是你的想法完全错误。数据的格式化应该在表示层(在这种情况下为 SSRS)而不是 RDBMS 中处理。尽管您可以动态声明具有动态精度或比例的内容,但您必须使用动态 SQL,这可能会使事情严重过度复杂化,并且可能会破坏您的 SSRS 报告,除非您了解如何实现动态语句成功进入SSRS。

相反,您应该使用表示层来确定格式。这在 SSRS 中并不是特别容易,但也不难。 假设您在 SSRS 报告中有一个参数Precision,它被定义为Integer。我还将使用来自以下 SQL 的基本数据集:

SELECT d
FROM (VALUES(10),(10.1),(10.12),(10.123),(10.1234))V(d);

这意味着您的报告可能有点像这样:

右键单击空白处,然后选择报告属性并转到代码窗格。然后输入以下代码:

Public Function DynamicPrecision(ByVal Precision AS Integer) AS String

    Dim I AS Integer
    If Precision = 0
        DynamicPrecision = "#,#"
    Else
        DynamicPrecision = "#,#."
        For I = 1 to Precision
            DynamicPrecision = DynamicPrecision & "0"
        Next I
    End If
End Function

现在单击您想要动态精度的单元格(或按住控件并单击单元格),然后按 F4 打开属性窗格。在属性窗格中进行精细格式化,然后下拉并选择“«表达式»”。然后输入以下表达式:

=Code.DynamicPrecision(Parameters!Precision.Value)

然后您的单元格将动态格式化为该精度。

因此,对于 024,数据将如下所示:

【讨论】:

  • 谢谢详细解释..我会试试这个
  • 比 FormatNumber..like =FormatNumber(Fields!Test.Value,Parameters!DecimalPrecision.Value) 有什么优势
  • 我发现设置单元格的格式比更改值的格式(并将其转换为字符串)@vmb 更可靠。
  • FormatNumber 会将其转换为字符串?如果我们将结果导出到 excel,它会将数据视为字符串?
  • 可能,但我的观点没有改变,为什么格式是字符串,而不是改变单元格的格式?单元格具有格式属性是有原因的;定义所述单元格的属性。
【解决方案2】:

ROUND,然后是 FORMAT。例如

 DECLARE @precison int = 2
 select format(round( (10.56/10.25),  @precison),'#,####.##')

或者只是 ROUND 让前端选择显示格式。

【讨论】:

  • 然而,这确实意味着varchar 被传递到表示层。我希望 OP 没有进行任何聚合或表达式,并且期望数字数据类型。 '1,000.00' + '123.00' 等于错误或'1,000.00123.00'
  • @David..它应该作为十进制本身传递给表示层..我认为上面的解决方案将它作为字符串传递
  • 然后只需四舍五入到所需的小数位数。不需要动态改变返回数据的数据类型。
  • SELECT ROUND(10.9999/10.456, 2) 将返回 1.0500000000..但我需要的是结果应该返回“1.05”
  • "1.05" 是一个字符串。 .NET(因此 SSRS)没有任何数据类型可以区分 1.05 作为小数(10,2)和 1.05 作为小数(10,5),因为 .NET 有一个十进制数据类型。
猜你喜欢
  • 2015-09-08
  • 2012-07-05
  • 2019-05-23
  • 2017-09-25
  • 2021-06-15
  • 1970-01-01
  • 2011-10-28
  • 2013-05-15
  • 1970-01-01
相关资源
最近更新 更多