Árvore de páginas

FAQ: DBOs com encadeamento de EACH
Produto:Datasul
Ambiente:Unspecified
Versão:4
Sintoma

DBOs com encadeamento de EACH

Causa

DBOs com encadeamento de EACH

Solução

Sintoma:

Um comando REPOSITION QUERY falha, mesmo utilizando um rowid existente e de um registro que esteja na query. Isso geralmente resulta na mensagem 11 (Não foi possível reposicionar a query). Também as telas ficam com os botões desabilitados, já que falhando o REPOSITION não haverá registro disponível, sendo assim interpretado como query sem registros.

Causa:

Esse problema ocorre em querys que possuem mais de uma tabela. É um erro comum inverter a ordem das tabelas, fazendo com que a tabela do DBO não seja a primeira. Veja o código abaixo, supondo que o mesmo se encontra na DBO da tabela "titulo".

define query qr1 for emitente, titulo.

open query qr1 for each emitente where emitente.nome-matriz = cNomeMatriz no-lock,
each titulo where titulo.cod-emitente = emitente.cod-emitente and titulo.vl-saldo > 0 and titulo.dt-emissao >= daDataIni and titulo.dt-emissao <= daDataFim no-lock.

Como o DBO pertence a tabela "titulo", o ROWID retornado será o ROWID desta tabela. Desta forma, ao tentar efetuar um REPOSITION QUERY neste DBO, nenhum registro será encontrado, visto que o REPOSITION QUERY é sempre efetuado na primeira tabela do OPEN QUERY. No entanto, o ROWID informado neste caso pertence a segunda tabela.

Cannot reposition query to recid/rowid given.

Solução:

Para resolver esse problema, a solução é inverter a ordem das tabelas, de forma que a tabela do DBO seja a primeira no OPEN QUERY. Utilizando novamente o DBO da tabela "titulo", o exemplo anterior ficaria assim:

define query qr2 for titulo, emitente.

open query qr2 for each titulo no-lock where titulo.vl-saldo > 0 and titulo.dt-emissao >= daDataIni and titulo.dt-emissao <= daDataFim, each emitente no-lock where emitente.nome-matriz = cNomeMatriz and emitente.cod-emitente = titulo.cod-emitente.

IMPORTANTE:

Como efeito colateral dessa inversão, pode haver uma queda de performance, causada pelo aumento do número de registros lidos. Isso ocorre porque, geralmente, a segunda tabela é posta como segunda justamente porque é maior.

Usando o exemplo anterior. Supondo que a tabela emitente tenha 10 registros e para cada registro de emitente existem 100 registros de titulo. Através do WHERE apenas 2 registros de emitente deverão ser selecionados.

Usando a primeira opção (qr1), são lidos os 2 registros da tabela emitente e para cada um deles são lidos os 100 da tabela título, totalizando 202 registros (2 de emitente e 200 de titulo).

Usando a segunda opção (qr2), são lidos os 1000 registros da tabela titulo (10 * 100), e para cada um deles é lido também o respectivo registro de emitente. Como apenas 2 emitentes atendem a condição do WHERE, os mesmos 200 registros de titulo ficarão de fato disponiveis na query, ignorando os demais 800 registros de titulo que foram lidos.

Para minimizar este efeito deve-se colocar o máximo de restrições possíveis no WHERE da primeira tabela.