Delphi TADOQuery.next跳过记录

时间:2015-06-23 17:49:09

标签: delphi tadoquery

申请/处理说明

我在Delphi XE中维护一些旧代码。应用程序在远程服务器上的数据库上运行查询,然后在PC上创建报告。我们有一个错误报告,其中一个字段中的某些数据丢失了。有问题的字段包含从服务器收集的大量数据(几千个字符)。我无法控制在此字段中收集和存储的数据。我发现错误是由嵌入在此数据中的空值和其他控制字符(换行符等)引起的。当调用TADOQuery的SaveToFile方法时,空值和其他控制字符会导致以后在字段中的任何数据被忽略(SaveToFile基本上到达控制字符并停止读取记录)。

该错误的解决方案是从结果集中提取有问题的字段,过滤掉任何控制字符并将其保存到临时文件中(此时我无法将其重新置于结果集中)处于只读状态)。数据保存为XML,因此我还必须使一些字符XML友好(正如您在代码片段中看到的那样)。调用SaveToFile方法后,我将从临时文件中读取更正后的数据并将其写回保存的报告中。它啰嗦但却有效。

问题

我现在遇到了一个新问题。我注意到在随机的情况下,文件末尾会丢失一条记录(相关字段将为空白)。我花了很多时间深入研究这个问题,它归结为以下代码(用于在调用SaveToFile之前从字段中提取数据)。代码正在跳过一行。不是每次 - 每两到三次查询运行一次。我知道这是因为我在调试时向下面的循环添加了一个计数器,并将循环执行的次数与记录计数进行了比较,并且当错误发生时它返回少一个(导致空白字段)并且当所有数据出现在报告中时相等。没有例外,所以它不会落在某些东西上 - 它实际上是在跳过一条记录。

assignfile(f, tempFilename);
rewrite(f);
adoqry.first;
repeat  
    try
        bytes := adoqry.fieldByName(fld).AsBytes;
        tmp := '';
        for i := 0 to length(bytes) - 1 do
            if bytes[i] < 32 then    // strip any control characters (nulls, line feeds etc.) from the string
                 tmp := tmp + ' '
            else
            begin
                 case char(bytes[i]) of
                      '&': tmp := tmp + '&amp;';
                      '''': tmp := tmp + '&apos;';
                      '"': tmp := tmp + '&quot;';
                      '>': tmp := tmp + '&gt;';
                      '<': tmp := tmp + '&lt;';
                 else
                      tmp := tmp + char(bytes[i]);
                 end;
            end;
        // when debugging, inc counter here to prove that the loop has been executed
        writeln(f, UTF8String(tmp));
        setLength(bytes, 0);
    except on e: exception do
        writeln(f, '');
    end;
    adoqry.next;
until adoqry.eof;
closefile(f);

问题

上述代码是否有任何理由会跳过记录(即只执行循环n-1次,其中n是记录计数)?有什么东西可以导致&#34; adoquery.next&#34;打电话跳过记录?

修改以澄清评论中提出的问题

报告中缺少数据。它始终是一个没有被处理的记录。我在报告中有超过20,000条记录,缺失的记录位于中间位置,但由于数据太多而难以缩小记录。当单个记录被跳过时,该记录之后的所有内容都会向上移动一条记录(意味着很多报告都是错误的),最终记录包含一个空白字段。

1 个答案:

答案 0 :(得分:0)

我似乎偶然发现了这个问题的解决方案。我还在测试,但目前似乎已经修好了。

在我进入之前,我追踪了被跳过的记录。有许多记录具有完全相同的数据。我删除了被跳过的记录,看看会发生什么,并且处理跳过了不同的记录(包含相同的数据)。和以前一样,它只是间歇性地跳过它(每两次或三次查询运行一次)。

进入“修复”...

我认为我会尝试对TADOQuery的配置进行一些调整,看看是否有任何影响。多年来,它已经运行良好,配置了以下选项:

adoqry.executeOptions := [eoAsyncFetch];

我评论了这一行,突然处理工作正常。我已经运行了几个查询,他们都回来了所有行。什么都没有被跳过。我会继续测试,但这似乎(目前)有固定的东西。