* With PK ? TablesAreIdentical('myTable1.dbf','myTable2.dbf',"myPK","myPK") * No PK but Field1+Field2 defines a record uniquely ? TablesAreIdentical('myTable1.dbf','myTable2.dbf',"myField1+myField2") * No expression to define a record uniquely * and didn't even want to create using all fields, * expecting they should be in same physical entry order ? TablesAreIdentical('myTable1.dbf','myTable2.dbf') Function TablesAreIdentical Lparameters tcTable1, tcTable2, tcPKExpr, tcPKTag Local lcAlias, lcOldDeleted, llMisMatch lcAlias = Alias() lcOldDeleted = Set('deleted') * We don't want to check if deleted match too Set Deleted On Use (tcTable1) In 0 Again Alias '_cmp1' Use (tcTable2) In 0 Again Alias '_cmp2' Local Array arrCnt1[1],arCnt2[1] Select Cnt(*) From _cmp1 Into Array arrCnt1 Select Cnt(*) From _cmp2 Into Array arrCnt2 If arrCnt1 # arrCnt2 llMisMatch = .T. && Reccount mismatch Else Local loRecord1, loRecord2, llUseSeek, llUseLocate, luValue llUseSeek = (!Empty(tcPKTag) And !Empty(tcPKExpr)) llUseLocate = (!llUseSeek And !Empty(tcPKExpr)) Select _cmp1 Scan * If not both indexed use indexed one as table2 * If none indexed but has unique field(s) use locate * If no unique field(s) then use recno instead Do Case Case llUseSeek If !Seek(&tcPKExpr, '_cmp2', tcPKTag) llMisMatch = .T. Exit Endif Case llUseLocate luValue = &tcPKExpr Select _cmp2 Locate For &tcPKExpr = luValue If Eof() llMisMatch = .T. Exit Endif Otherwise Go Recno('_cmp1') In '_cmp2' Endcase Select _cmp2 Scatter Name loRecord2 Memo Select _cmp1 Scatter Name loRecord1 Memo If !Compobj(loRecord1, loRecord2) llMisMatch = .T. Exit Endif Endscan Endif Use In '_cmp1' Use In '_cmp2' If !Empty(lcAlias) Select (lcAlias) Endif Set Deleted &lcOldDeleted Return !llMisMatchAnd still yet there might be other comparison needs.