如何在sql server中的标量函数中传递列名[关闭]
Posted
技术标签:
【中文标题】如何在sql server中的标量函数中传递列名[关闭]【英文标题】:How to pass column name in scalar function in sql server [closed] 【发布时间】:2012-12-25 10:34:58 【问题描述】:我在 sql server 中创建一个标量函数。并在函数中传递列名作为参数。在这个函数中,我将这些列名与该表一起使用。这里@FromCurrency
和@ToCurrency
是CurrencyConversion
表的列名。
代码如下:
alter FUNCTION fnCurrencyConversion --1200.90,'NGN','CAD'
(@MoneyAmount MONEY,
@FromCurrency nvarchar(20),
@ToCurrency nvarchar(20))
RETURNS decimal(18,2)
AS
BEGIN
declare @BaseToUsd nvarchar(1000), @UsdToTarget nvarchar(1000)
declare @Rate decimal(18,5)
set @BaseToUsd= ('select top 1 '+ @FromCurrency +' from CurrencyConversion order by id desc')
set @UsdToTarget = ('select top 1 '+ @ToCurrency +' from CurrencyConversion order by id desc')
set @Rate = @UsdToTarget/@BaseToUsd
declare @TotalAmt decimal(18,5)
set @TotalAmt = (@Rate * @MoneyAmount)
return @TotalAmt
END
如何在sql的标量值函数中传递列名?
【问题讨论】:
UDF 不支持使用动态 SQL,即使他们使用了错误的语法。 【参考方案1】:UDF 不支持使用动态 SQL,即使它们使用了错误的语法。
您可以按照以下方式创建一个执行此操作的存储过程:
create procedure procCurrencyConversion --1200.90,'NGN','CAD'
(@MoneyAmount MONEY,
@FromCurrency nvarchar(20),
@ToCurrency nvarchar(20))
AS
BEGIN
declare @BaseToUsd nvarchar(1000), @UsdToTarget nvarchar(1000)
declare @Rate decimal(18,5)
declare @SQL nvarchar(4000)
set @SQL = 'select top 1 @BaseToUsd ='+ @FromCurrency +N' from CurrencyConversion order by id desc'
exec sp_executesql @SQL, N'@BaseToUsd nvarchar(1000) output', @BaseToUsd output
set @SQL = 'select top 1 @UsdToTarget='+ @ToCurrency +N' from CurrencyConversion order by id desc'
exec sp_executesql @SQL, N'@UsdToTarget nvarchar(1000) output', @UsdToTarget output
set @Rate = @UsdToTarget/@BaseToUsd
declare @TotalAmt decimal(18,5)
set @TotalAmt = (@Rate * @MoneyAmount)
select @TotalAmt
END
请注意,sp_executesql 的语法非常简洁,不适合装腔作势:)
此外,我建议规范化 CurrencyConversion
表,这样您就可以在没有动态 SQL 的情况下获取数据,类似于 Currency
列并为每种货币插入一行,而不是为每种货币使用单独的字段。
此外,请尽量避免使用 UDF,尤其是在大型数据集上,因为它们以逐行痛苦的方式工作,并且是巨大的性能瓶颈。
【讨论】:
您认为当前的CurrencyConversion
表打破了什么规范化规则? 1NF?它不是与phone1,phone2
IMO 相同的重复组,因为这些列代表不同的货币,而不是同一事物的多个实例。
@MartinSmith 是的,它是一个重复组(1 列),是的,它们是“货币价值”事物的多个实例。这更像是“verizon-phone”、“tmobile-phone”、“att-phone”的情况,但还是一样的。
所以如果一个表有列startDate
和endDate
你还会说它有多个“日期值”的实例吗? - 对重构没有争议,因此添加新货币不涉及添加列可能不是一个坏主意,但不确定it breaks 1NF
@MartinSmith:不,这些是严格定义的,新的midDate
似乎不太可能。 startDate
和 endDate
也可以有不同的用法和规则(即start
不为空,end
为空)。另一方面,货币都有相同的规则和计算可供它们使用。
我得再考虑一遍!以上是关于如何在sql server中的标量函数中传递列名[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MS Access VB 中访问 SQL Server 标量函数
我应该如何使用 sql server 中的存储过程将列名存储在变量中?