2つのデータベースがあり、一方のデータベースのすべてのレコードがもう一方のデータベースに一致するレコードを持っていることを確認する必要があります。これらをDB-SQLおよびDB-Legacyと呼びます
両方にSQLインターフェイスがあれば、これは十分に簡単ですが、残念ながら、私は一方にしかアクセスできず、もう一方には「レコードの検索/最初/次」タイプのインターフェイスがあります。
このタスクを実行するために選択した方法は、以下のコードを介してDB-SQLをclientdatasetに転送することです。
var
lQuery: TADOQuery;
lProvider: TDataSetProvider;
lDataSet: TClientDataSet;
begin
lQuery := TADOQuery.Create(nil);
lProvider := TDataSetProvider.Create(nil);
lDataSet := TClientDataSet.Create(nil);
// we don't need either of these and should speed things up
lDataSet.disablecontrols;
lQuery.DisableControls;
try
lQuery.Connection := aConnection;
lQuery.SQL.Add('SELECT FieldA, FieldB, FieldC, 0 as FoundInGIS');
lQuery.SQL.Add('FROM TableA');
// following two lines needed to allow us to modify the FoundInGIS field in the clientdataset
lQuery.open;
lquery.fieldbyname('FoundInGIS').Readonly := false;
lProvider.DataSet := lQuery;
lDataSet.Data := lProvider.Data;
lDataSet.fieldbyname('FoundInGIS').readonly := false;
lDataSet.LogChanges := false;
// index by FieldA for quick searching by FindKey later
lDataSet.IndexFieldNames := 'FieldA';
finally
lQuery.Free;
lProvider.Free;
end;
これは、 http://www.podgoretsky.com/ftp/docs/Delphi/D5/dg/5_ds3.html#20536のコードに基づいています。
これにより、EOFまでFirst / NextでDB-legacyを反復処理し、FindKeyを使用してClientDataSetを検索し、DB-LegacyのすべてのレコードがDB-SQLに存在することを確認できます。FoundInGISタグを1に設定することで、この値でフィルタリングして、DB-SQLにはあるが、DB-Legacyにはないすべてのレコードを見つけることができます。
私の問題は、私たちのデータベースの1つが他のデータベースよりも大幅に大きく、3,310,510レコードであるということです。lQueryには正しい数のレコードがありますが、プロシージャの最後では、lDataSetには約2,500,000しかありません。
ここで、CDを使用してFindKeyメソッドを使用したいと思います。これは、TADOQueryでサポートされていませんが、レコードの3分の1を無視する場合は、あまり使用されません。DataSetProviderまたはClientDataSet内のどこかに整数のオーバーフローがあるかもしれないと推測していますが、例外が発生しないのは少しやんちゃです!他の誰かがこの種の問題を抱えていましたか?それを並べ替える方法はありますか(おそらく、データを小さなチャンクにダウンロードするか、CDSにデータを取り込む別の方法を使用することによって)?
この場合のSQL-DBはOracleですが、DBの問題ではないかと思いますが、コードもSQL-Serverで動作する必要があります。
編集:私は今、いくつかのわずかに異なる動作をしています。クエリからいくつかのフィールドを削除しようとすると、正常に実行されます。すべてのフィールドは個別に正常に実行されますが、すべてを処理することはできません(これは私のオーバーフロー仮説をサポートします)。私は今ですが、時々例外が発生します。例外は
'Format '%s' invalid or incompatible with argument'
これは誤解を招く可能性があります。デバッグDCUを詳しく調べると、エラーが次の原因で発生していることがわかります。
SafeArrayCheck(SafeArrayCopy(VarToDataPacket(Value), FSavedPacket));
TCustomClientDataSet.SetData(DBClient行1482)。これにより、ESafeArrayError(AResult = -2147024882)が発生し、「予期しないバリアントまたは安全な配列エラー」になりますが、その後のFormatStrの呼び出しを処理できません。