提问人:John 提问时间:9/7/2023 最后编辑:John 更新时间:9/9/2023 访问量:51
将 Access 函数转换为 SQL Server 时出现问题
Trouble converting an Access Function to SQL Server
问:
SQL学习者在这里。我在通过 SQL Server 转换 Microsoft Access 中内置的函数时遇到问题。 下面是 Access 中显示的函数。
Function DatePop(DATE)
Dim DateMin As Date
Dim DateMax As Date
DateMin = "01/10"
DateMax = CDate(Now())
If (Format(DATE, "dd/mm") >= DateMin
Or
Format(DATE, "dd/mm") <= DateMax)
Then DatePop = 1
Else DatePop = 0
End If
End Function
如果日期在 10 月 1 日之后且在当前日期之前,则该函数的目标是返回 1。否则返回 0。
答:
好的,让我们将 VBA 函数重写为 T-SQL。 创建此类函数后,可以在 T-SQL 代码中使用该函数(就像我们在 VBA 代码中所做的那样)。这些函数现在可以在任何 SQL Server SQL 表达式中自由使用。(同样,就像在 JET/ACE SQL 表达式中使用此类 VBA 函数一样)。
因此,在 T-SQL 中创建此类函数时存在 1 对 1 对称性,从那时起,转换为 T-SQL 代码的任何 VBA 代码现在都可以使用你创建的该函数。对于您编写服务器端的任何 SQL,该函数都可以在您编写的 SQL 中自由使用(同样,就像在 Access 中编写 SQL 并在您编写的 SQL 中使用 VBA 表达式一样)。
此外,您发布的函数中仍然存在一些“歧义”。它似乎依赖于“忽略”当前年份的字符串比较这一事实。这是一些“高风险”,因为台式计算机上区域设置的任何更改都会导致此类代码中断。
当你说“十月之后”时,你是指当年,还是任何时间和任何年份的任何日期,其中“月”在十月之后?这看起来像现在代码的工作方式,即使这不是你的本意。
不要使用保留词作为变量名称,因为它们只会在这里造成痛苦和折磨。
因此,让我们首先让这个VBA代码正常工作,或者更好地说明,以这样一种方式定义,我们可以100%清楚逻辑。因此,当我们花费时间和精力时,我们正在将有效代码转换为 T-SQL。
因此,根据您所拥有的,这看起来像是等变VBA代码:
Public Function DatePop(nDate) As Integer
Dim ToDay As Date
Dim iMonth As Integer
Dim iDay As Integer
iMonth = 10
iDay = 1
If IsNull(nDate) Then
DatePop = 0
Exit Function
End If
ToDay = CDate(Now())
If (Month(nDate) >= iMonth) And (Day(nDate) > iDay) Then
DatePop = 1
Exit Function
End If
If nDate <= ToDay Then
DatePop = 1
Exit Function
End If
DatePop = 0
End Function
如前所述,您注意到了“10 月之后”的逻辑,但您的意思是任何一年,还是仅指此逻辑的当前年份?
并注意我们如何强制(定义)函数返回的数据类型。再一次,我们不能把它留给风吹。
好的,基于上面的代码,我们现在可以将上面的 VBA 代码转换并重写成执行相同操作的 T-SQL 函数。
因此,此 T-SQL 应该有效:
CREATE FUNCTION DatePop
(
@nDate date
)
RETURNS int
AS
BEGIN
DECLARE @iMonth int
DECLARE @iDay int
DECLARE @ToDay date
DECLARE @iResult int
set @iResult = 0
set @iMonth = 10
set @iDay = 1
set @ToDay = CAST(GETDATE() as date) -- date without time
if month(@nDate) >= @iMonth AND day(@nDate) >= @iDay
BEGIN
set @iResult = 1
END
if @nDate <= @ToDay
BEGIN
set @iResult = 1
END
RETURN @iResult
END
一旦创建了上述功能?那么这应该像VBA函数一样工作。这包括在 VBA 代码(或现在的 T-SQL 代码)中使用该函数,并且还包括在编写的服务器端 T-SQL 代码中自由使用此函数。
唯一值得注意的区别是 T-SQL 函数必须以 dbo 为前缀。(函数所属的架构)。因此,当您将 JET/ACE SQL 剪切 + 粘贴到 SQL Server 中时,通常相同的 SQL 可以工作,但您必须编辑该 SQL 中使用的 VBA 函数,并以 dbo 为前缀。
因此:
SELECT ID, HotelName, BookingDate, DatePop([BookingDate]) as MySeason
FROM Hotels
如果将上述内容剪切+粘贴到SQL Server,则将变为:
SELECT ID, HotelName, BookingDate, dbo.DatePop([BookingDate]) as MySeason
FROM Hotels
请注意,在上面,我们必须用“dbo.”来“前缀”DatePop 函数。
评论
IIF(date_col BETWEEN '20221001' AND GETDATE(),1,0)
date_col
date
WHERE date_col BETWEEN '20221001' AND GETDATE()
date_col
datetime
datetime2
WHERE DATE_COL BETWEEN @date1 and @date2