将FoxPro的SQL代码转换为sqlserver代码
我正在尝试将一些代码从FoxPro翻译成sqlserver,我面临着非常奇怪的行为 这段代码是在FoxPro的应用程序中编写的:将FoxPro的SQL代码转换为sqlserver代码,sql,translation,foxpro,visual-foxpro,Sql,Translation,Foxpro,Visual Foxpro,我正在尝试将一些代码从FoxPro翻译成sqlserver,我面临着非常奇怪的行为 这段代码是在FoxPro的应用程序中编写的: lcZnak1 = "HM,P6"; SELECT Zakslozkap.datum,ABS(Zakslozkap.hodnota) hodnota, ABS(Zakslozkap.koruny) koruny, Zakslozka.sekce; FROM Zakslozkap, Zakslozka; WHERE (Zakslozkap.SW $ lcZnak1)
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的结果
所以,有10万的差别,因为这是关于钱的,所以差别很大。我在拼命寻找解决办法,所以我在那里问。我的SQL翻译是否准确地反映了来自FoxPro的代码
表是相同的,所以数据是相同的。在SQL中,我使用链接服务器访问这些DBF。字段koruny作为float数据类型存储在dbf中。如果有人将数据从VFP转换到SQL server,我想知道VFP中是否有标记为删除的记录没有上载到SQL server。这在VFP中通过使用SET DELETED ON隐藏标记为删除的记录来处理。设置“已删除”以允许查看已删除的记录,并最终将其包含在查询中 也就是说,我将通过检查SQL中的@@rowcount来确认查询中正在处理的记录数,看看它是否匹配 现在,有些事情不完全是VFP是如何做的,但基于概率,我认为你在其他方面还行,这是关于VFP中的$。$用于表示在右边字符串的任何位置左边的东西
lcZnak1 = "HM,P6";
WHERE (Zakslozkap.SW $ lcZnak1)
您的转换为
其中p.SW='HM'或p.SW='P6'
可能没问题,但区别在这里
假设您在SW列中有一个值,即M或p,甚至是M或p,甚至是HM、p、HM、P6等等,所有这些都符合条件。这几乎就像SQL中的like命令。同样地,你在底部的总结。但是,如果您的列的宽度为x个字符,以匹配您要查找的内容,那么您的状态可能很好
所以,我想从转换的角度考虑记录的删除状态。您还可以通过先执行以下操作来测试VFP端查询
设置删除日期
执行var和查询的其余部分
启用“已删除”时,您将忽略所有已删除的记录。在您的筛选器中有一个基于日期的筛选。当需要筛选日期时间时,不应在SQL server中使用between或between。这是一个错误源,您可能会错过应该在选择列表中的记录,或者您可能会得到比您应该看到的更多的记录,因为无法使用between正确定义日期时间范围 您还应该记住,在SQLServer中,您的值很可能是datetime值,而在VFP中可能使用了date。确保选择的范围相同 考虑这种情况: 您有saleTime表示销售发生日期时间的sales。如果你想获得2013年1月的所有销售额,你怎么能在两者之间写出这些呢?不可能 set@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设置为大于所需最大时间的最小时间。要正确获取2013年1月,请执行以下操作: set@dateStart='2013/1/1' set@dateEnd='2013/2/1'-表示2013年2月1日00:00:00。我们要排除的最短时间
select ... from ... where saleTime >= @dateStart and saleTime < @dateEnd
是具有日期时间范围的正确查询。这两个查询各自返回什么?他们有相同的结果集吗?我指的是两个完整的select语句。