Foxpro SQL 语句中出现意外的笛卡尔积

Unexpected cartesian product in Foxpro SQL statement

我正在从 C# 程序中执行以下 Visual FoxPro SQL 语句。我希望得到 1 个结果,但我没有得到任何结果。

SELECT 
    iplclaim.lc_lname, ipcname.cn_lname, ipcbusn.cb_bname   ;
FROM 
    iplclaim  ;
INNER JOIN 
    iplclsub ON iplclsub.ls_claimno + iplclsub.ls_sclaimno = iplclaim.lc_claimno + 'A' ;
LEFT OUTER JOIN 
    ipcname ON ipcname.cn_inqno = iplclsub.ls_inqno  ;
LEFT OUTER JOIN 
    ipcbusn ON ipcbusn.cb_inqno = iplclsub.ls_inqno  ;
WHERE 
    iplclaim.lc_claimno = '  1105'     ;
    AND NOT DELETED() 

我可以使用以下程序从 VFP 重现问题 运行ning...

CLOSE DATABASES all
OPEN DATABASE ipcust.dbc
USE C:\TESTVFP\IPS\DATA\PPDATA\IPlclaim IN 0
USE C:\TESTVFP\IPS\DATA\PPDATA\iplclsub IN 0
USE C:\TESTVFP\IPS\DATA\PPDATA\IPcname IN 0
USE C:\TESTVFP\IPS\DATA\PPDATA\IPcbusn IN 0
SYS(3054,12)

SELECT iplclaim.lc_lname, ipcname.cn_lname, ipcbusn.cb_bname   ;
 FROM iplclaim  ;
INNER JOIN iplclsub ON iplclsub.ls_claimno + iplclsub.ls_sclaimno = '  1105A'     ;
 LEFT OUTER JOIN ipcname ON ipcname.cn_inqno = iplclsub.ls_inqno  ;
 LEFT OUTER JOIN ipcbusn ON ipcbusn.cb_inqno = iplclsub.ls_inqno  ;
WHERE iplclaim.lc_claimno = '  1105' ;
  AND NOT DELETED() 

似乎如果在程序执行前没有打开表,结果是零记录。如果我打开表格并只执行 SQL 语句,它 returns 预期的一条记录。

另一件我没想到的事情是,当我 运行 上面的程序时,SYS(3054,12) returns 结果如下(注意 "Cartesian product") ...

SELECT ipcname.cn_lname, ipcbusn.cb_bname FROM iplclsub LEFT OUTER JOIN ipcname ON ipcname.cn_inqno = iplclsub.ls_inqno LEFT OUTER JOIN ipcbusn ON ipcbusn.cb_inqno = iplclsub.ls_inqno WHERE  iplclsub.ls_claimno + iplclsub.ls_sclaimno = '  1105A' AND NOT ip
Using index tag Claimall to rushmore optimize table iplclsub
Rushmore optimization level for table iplclsub: partial
Rushmore optimization level for table ipcname: none
Rushmore optimization level for table ipcbusn: none
Joining table iplclsub and table ipcname (Cartesian product)
Joining intermediate result and table ipcbusn (Cartesian product)

但是当我 运行 单独使用表已经打开的 SQL 语句时,输出看起来不同(注意没有 "Cartisian product")

SELECT ipcname.cn_lname, ipcbusn.cb_bname FROM iplclsub LEFT OUTER JOIN ipcname ON ipcname.cn_inqno = iplclsub.ls_inqno LEFT OUTER JOIN ipcbusn ON ipcbusn.cb_inqno = iplclsub.ls_inqno WHERE  iplclsub.ls_claimno + iplclsub.ls_sclaimno = '  1105A' AND NOT ip
Using index tag Claimall to rushmore optimize table iplclsub
Rushmore optimization level for table iplclsub: partial
Rushmore optimization level for table ipcname: none
Rushmore optimization level for table ipcbusn: none
Joining table iplclsub and table ipcname using tag Inqno
Joining intermediate result and table ipcbusn using tag Inqno

最后说明: iplclaim 中只有一条记录与 WHERE 子句匹配。 iplclsub 中只有一条记录匹配 INNER JOIN iplclsub ON 子句。 ipcname中只有一条记录匹配LEFT OUTER JOIN ipcname ON子句,ipcbusn中没有匹配LEFT OUTER JOIN ipbusn ON子句的记录。

任何人都可以解释导致此问题的原因以及我必须做些什么来解决它吗?

编辑:

好吧,我发现问题出在 AND NOT DELETED()。如果我删除该条款,一切都会按预期进行。谁能解释一下,谁能告诉我排除已删除记录的替代方法?

FoxPro 文档中有一条关于 SELECT-SQL 命令在多个 table 查询中使用 DELETED() 等函数时可能返回意外结果的警告。

SET DELETED ON 命令可用于忽略标记为删除的记录。启用该选项后,似乎可以从查询中删除 DELETED() 函数的使用。

对于 C# 代码,假设您使用的是 OLEDB 连接,可以在执行查询之前在同一个打开的 FoxPro 连接上执行 SET DELETED ON 命令。