将FoxPro转T-SQL:lcCMGTVendor在最终查询中的作用困惑
解惑:Visual FoxPro中lcCMGTVendor的作用及T-SQL转换思路
首先要明确:这段FoxPro代码里的lcCMGTVendor并不是用来过滤数据的,而是作为常量给结果集的provkey字段统一赋值,这是符合这段代码的业务逻辑的,我帮你拆解清楚:
1. lcCMGTVendor的来源
它是从系统配置表dbfs\am_opts中读取的固定配置值:
* 获取病例管理工时的供应商代码 Select op_value ; FROM dbfs\am_opts ; WHERE op_code = "CMGT_VENDOR" ; INTO CURSOR cmgt_vndr lcCMGTVendor = padr(cmgt_vndr.op_value, 4)
padr(cmgt_vndr.op_value, 4)的作用是把供应商代码补到4位长度(不足的话右侧补空格),对应T-SQL里的LEFT(op_value + SPACE(4), 4)。
2. 代码的核心业务意图
这段代码的目的是:当满足llIncludeCMGT = .T.的条件时,把f_Rpt表中符合筛选规则的工时记录,统一归类到系统配置的CMGT供应商名下——也就是给这些记录的provkey字段强制设置为lcCMGTVendor的值,而不是筛选该供应商自己的记录。
你看到的最终查询:
select lcCMGTVendor as provkey, ; iif(empty(SQL_F_Rpt.sub_code), "CMGT", SQL_F_Rpt.sub_code) as sub_code, ; SQL_F_Rpt.keyfld, ; 00000.00 as tot_auth, ; (SQL_F_Rpt.unit * SQL_F_Rpt.cost) as tot_deliv, ; SQL_F_Rpt.start_dt as plandt ; from &SQL_FROM ; where &SQL_WHERE ; into cursor pass3
这里的lcCMGTVendor as provkey就是把这个配置值作为常量,给结果集中的每一行都设置相同的provkey,这是业务上的归类需求,逻辑是通顺的。
3. 对应的T-SQL转换思路
第一步:获取配置值
DECLARE @lcCMGTVendor VARCHAR(4); SELECT TOP 1 @lcCMGTVendor = LEFT(op_value + SPACE(4), 4) FROM dbfs.am_opts -- 假设已映射为SQL Server表 WHERE op_code = 'CMGT_VENDOR';
第二步:处理llIncludeCMGT的判断逻辑
把FoxPro中的游标判断(_tally > 0)和变量判断转换成T-SQL的BIT变量:
DECLARE @llIncludeCMGT BIT = 0; -- 对应原代码中判断是否有符合条件的服务 IF EXISTS(SELECT 1 FROM tempsrv WHERE Is_It_Case_Service(sub_code) = 1 AND selected = 1) OR @pcService = 'ALL' BEGIN SET @llIncludeCMGT = 1; END -- 再判断是否限定了特定供应商 IF @llIncludeCMGT = 1 AND @pcVendor <> 'ALL' BEGIN -- 检查配置的CMGT供应商是否在选中的供应商列表中 IF NOT EXISTS(SELECT 1 FROM TempVnd WHERE provkey = @lcCMGTVendor AND Selected = 1) BEGIN SET @llIncludeCMGT = 0; END END
第三步:执行最终查询(当需要纳入CMGT工时)
IF @llIncludeCMGT = 1 BEGIN -- 先构建动态SQL(对应原代码的&SQL_FROM和&SQL_WHERE),或者用静态查询拼接 DECLARE @SQL_FROM NVARCHAR(MAX) = 'SQL_F_Rpt'; -- 假设SQL_F_Rpt是f_Rpt的别名 DECLARE @SQL_WHERE NVARCHAR(MAX) = 'SQL_F_Rpt.End_Dt BETWEEN @pdBegin_Date AND @pdEnd_Date AND IS_IT_WAIVER(SQL_F_Rpt.Payor, 0) = 0'; -- 处理付款方筛选 IF @pcPayor <> 'ALL' BEGIN SET @SQL_FROM += ', TempPay'; SET @SQL_WHERE += ' AND SQL_F_Rpt.Payor = TempPay.Payor_CD AND TempPay.Selected = 1'; END -- 处理服务代码筛选 IF @pcService <> 'ALL' BEGIN SET @SQL_FROM += ', TempSrv'; SET @SQL_WHERE += ' AND ISNULL(NULLIF(SQL_F_Rpt.Sub_Code, ''''), ''CMGT'') = TempSrv.Sub_Code AND TempSrv.Selected = 1'; END -- 执行动态查询 DECLARE @FullSQL NVARCHAR(MAX) = N' SELECT @lcCMGTVendor AS provkey, ISNULL(NULLIF(SQL_F_Rpt.sub_code, ''''), ''CMGT'') AS sub_code, SQL_F_Rpt.keyfld, 0.00 AS tot_auth, (SQL_F_Rpt.unit * SQL_F_Rpt.cost) AS tot_deliv, SQL_F_Rpt.start_dt AS plandt FROM ' + @SQL_FROM + ' WHERE ' + @SQL_WHERE; EXEC sp_executesql @FullSQL, N'@lcCMGTVendor VARCHAR(4), @pdBegin_Date DATE, @pdEnd_Date DATE', @lcCMGTVendor = @lcCMGTVendor, @pdBegin_Date = @pdBegin_Date, @pdEnd_Date = @pdEnd_Date; END
总结一下:原FoxPro代码中lcCMGTVendor的作用是给符合条件的工时记录统一设置供应商代码,而不是筛选数据,这个逻辑是业务需求决定的,并没有问题。
内容的提问来源于stack exchange,提问作者Chicken Sandwich No Pickles
相关产品推荐
相关产品推荐

