将 FoxPro 的 SQL 代码转换为 SQL Server 代码



我正在尝试将一些代码从FoxPro翻译成SQL Server,但我遇到了非常奇怪的行为。

在 FoxPro 的应用程序中编写的以下代码:

lcZnak1 = "HM,P6";
SELECT Zakslozkap.datum,ABS(Zakslozkap.hodnota) hodnota, ABS(Zakslozkap.koruny)
koruny, Zakslozka.sekce;
FROM Zakslozkap, Zakslozka; 
WHERE (Zakslozkap.SW $ lcZnak1) AND;
BETWEEN(Zakslozkap.datum,Thisform.cDatOd,Thisform.cDatDo) AND ;
Zakslozkap.ide_slozka = Zakslozka.ide_slozka AND ;
Zakslozka.ide_zak = "6065" ;
INTO CURSOR QueryNakladMZD
SUM (koruny) FOR  sekce $ ('REZIE4') TO lnostat
SUM (koruny) FOR  sekce $ ('REZIE3') TO lnRezie
SUM (koruny) FOR  sekce $ ('SEKTOR') TO lnSekce
SUM (koruny) TO lnPodil
lnPodil= lnPodil - lnostat - lnRezie - lnSekce

产生的结果为 lnPodil = 1 721 761,07。

我用SQL编写的代码:

declare @lnOstat decimal(18,5) = 0
declare @lnRezie decimal(18,5) = 0
declare @lnSekce decimal(18,5) = 0
declare @lnPodil decimal(18,5) = 0  
select p.datum, abs(p.hodnota) as 'hodnota', abs(p.koruny) as 'koruny', z.sekce into #tmp
from [DOCHAZKA]...[zakslozkap] p, [DOCHAZKA]...[zakslozka] z
where (p.SW = 'HM' or p.SW = 'P6')
      and p.datum between @datestart and @dateend
      and p.ide_slozka = z.ide_slozka
      and z.ide_zak = '6065'
select @lnOstat = SUM(koruny) from #tmp where sekce = 'REZIE4'
select @lnRezie = SUM(koruny) from #tmp where sekce = 'REZIE3'
select @lnSekce = SUM(koruny) from #tmp where sekce = 'SEKTOR'
select @lnPodil = SUM(koruny) from #tmp
select @lnPodil = isnull(@lnPodil,0) - isnull(@lnOstat,0) - isnull(@lnRezie,0) - isnull(@lnSekce,0) 
drop table #tmp

产生的结果为 @lnPodil = 1 623 779.67。

所以,

有100k的差异,因为这是关于钱的,所以很多。我迫切地在寻找解决方案,所以我在那里问。我的SQL翻译是否完全反映了FoxPro的代码?

表是相同的,所以数据是相同的。在SQL中,我使用链接服务器来访问这些dbfs。字段 "koruny" 作为浮点数据类型存储在 dbf 中。

如果有人将数据从 VFP 转换为 SQL 服务器,我想知道 VFP 中是否有标记为删除的记录未上传到 SQL 服务器。 这是在 VFP 中通过使用"设置删除时间"隐藏标记为删除的记录来处理的。 "设置已删除"以允许查看已删除的记录(并最终包含在您拥有的查询中)。

也就是说,我将通过检查 SQL 中的@@rowcount来确认查询中正在处理的记录的 COUNT,以查看它是否也匹配。

现在,有些事情并不是 VFP 如何"完全"做事,但根据概率,我认为你在其他方面还可以,这就是关于 VFP 中的"$"。 "$"用于表示是右侧字符串中左侧任何地方的东西......

lcZnak1 = "HM,P6";
WHERE (Zakslozkap.SW $ lcZnak1)

您的转换

其中 p.SW = 'HM' 或 p.SW = 'P6'

可能没问题,但这是区别

假设您在"M"或"P"

的"SW"列中有一个值,甚至是"M"或"P",甚至"HM,P","HM",",P6"等,所有这些都符合条件。 它几乎就像SQL中的LIKE命令。 同样在底部的总结中。 但是,如果您的列宽度为"x"个字符以匹配您要查找的内容,则您可能处于良好状态。

因此,综上所述,我会考虑转换中记录的"已删除"状态。 您还可以通过先执行以下操作来测试 VFP 端查询...

设置删除时间

执行其余的变量和查询。

打开"已删除"

,您将"忽略"任何已删除的记录。

在您的过滤器中,有一个基于日期的过滤。当您需要过滤日期(日期时间)时,不应在 SQL 服务器中使用 between() 或 Between 。它是错误的来源,您可能会错过应该在选择列表中的记录,或者您可能会获得比您应该看到的更多的记录(因为无法使用"between"正确定义日期时间范围)。

此外,还应记住,在 SQL Server 中,您的值可能是日期时间值,而您可能在 VFP 中使用了日期。请确保选择相同的范围。

考虑这种情况:

您有销售,其中销售时间表示销售发生的日期时间。您想获得 2013 年 1 月的所有销售,您如何使用两者来写?不可能。

集合@dateStart = '2013/1/1'设置@dateEnd = ???

如果设置@dateEnd:- 到 '2013/2/1',那么您可能会包括 2 月份的销售额。- 到 '2013/1/31' 那么你很可能错过了当月最后一天的销售- 到 '2013/1/31 23:59:59.xxx' 那么你可能会错过最后一天的一些销售(机会很小,但它发生了,SQL Server 敏感到 3 毫秒的分辨率)。

正确的方法是不使用 BETWEEN 并将 dateEnd 设置为大于所需最大时间的最小时间。IOW 正确获取 2013 年 1 月:

集合@dateStart = '2013/1/1'set @dateEnd = '2013/2/1' -- 表示 2013 年 2 月 1 日 00:00:00。我们要排除的最短时间

select ... from ... where saleTime >= @dateStart and saleTime < @dateEnd

是具有日期时间范围的正确查询。

相关内容

  • 没有找到相关文章

最新更新