Pragiva — Tecnologia na prática

Índices no Protheus: filial primeiro e nickname em tabela padrão

Índices no Protheus: por que o índice começa pela filial, como a ordem passa de 9 para A e por que um índice seu em tabela padrão precisa de nickname.

Protheus Referência técnica 6 min de leitura

Assista o vídeo

Resposta rápida

Onde fica
Configurador, no dicionário da tabela, opção Índices — gravado na SIX.
Regra quase sem exceção
o índice começa pelo campo de filial.
Ordem
um caractere só — de 1 a 9, depois A, B, C…
Quando o nickname importa
índice seu em tabela padrão.
Armadilha
dbSetOrder(n) num índice seu em tabela padrão aponta para outro índice depois de uma atualização.
Consulta rápida6 seções

Índice é o que permite ao Protheus ir direto a um registro em vez de ler a tabela inteira. Numa tabela sua, ele é quase burocracia: filial, código, pronto. Numa tabela padrão, o índice que você cria disputa espaço com os que a TOTVS entrega — e é aí que o nickname deixa de ser um campo opcional.

O que a SIX guarda

Cada linha da SIX é um índice. As colunas que decidem alguma coisa:

ColunaO que guarda
INDICEO alias da tabela (, ZA1)
ORDEMA posição do índice na tabela — um caractere
CHAVEA expressão da chave, campos somados com +
DESCRICAOO texto que o usuário vê ao escolher a ordem de pesquisa
PROPRIS no índice do padrão; numa base com customização, os criados pelo cliente aparecem com U
F3Consulta padrão associada ao índice (no padrão, a ordem 3 da SC5 usa CLI)
NICKNAMEO apelido do índice, de uso restrito em customizações
SHOWPESQS ou N: a opção Mostra Pesq da tela — com S, o índice é mostrado no browse

É a mesma estrutura para tabela padrão e customizada. A diferença está no que você faz com ela.

Filial primeiro

Veja os índices do pedido de venda no dicionário padrão:

OrdemChaveDescrição
1C5_FILIAL+C5_NUMNumero
2C5_FILIAL+DTOS(C5_EMISSAO)+C5_NUMDT Emissao + Numero
3C5_FILIAL+C5_CLIENTE+C5_LOJACLI+C5_NUMCliente + Loja + Numero
4C5_FILIAL+C5_OSGerado p/ OS
5C5_FILIAL+C5_NUMENTEntrega
6C5_FILIAL+C5_CODED+C5_NUMPRCod. Edital + Nr. Processo
7C5_FILIAL+C5_CODEMBCod. Embarc.
8C5_FILIAL+C5_MODANPModal ANP
9C5_FILIAL+C5_CODVGLPCod.Vas.GLP
AC5_FILIAL+C5_MDCONTR+C5_MDNUMED+C5_MDPLANINum.Contrato + Num.Medicao + Num.Planilha
BC5_FILIAL+C5_CLIENTE+C5_LOJACLI+DTOS(C5_EMISSAO)+C5_TIPOCliente + Loja + DT Emissao + Tipo Pedido

Três coisas saltam dessa tabela.

Todas começam por . A mesma tabela física guarda os registros de todas as filiais, e a busca parte de “desta filial”. Por isso o DbSeek num índice desses começa com xFilial("SC5"): a chave montada precisa casar com a chave do índice, na mesma ordem de campos. Num índice que começa por outro campo (as exceções logo abaixo), a chave do DbSeek segue aquele índice, não a regra.

No dicionário padrão inteiro, praticamente todos os índices seguem essa regra. As exceções existem e são deliberadas: índices que começam por outro campo de filial (a filial de entrega do pedido de compra, ), índices de busca global por um identificador (, no contas a receber) e alguns em que a filial vem depois do campo buscado. Para uma tabela sua, não há motivo para imitar a exceção: comece pela filial.

Depois do 9 vem o A. A ORDEM tem um caractere só. Passou de nove índices, a numeração segue em letras — no dicionário padrão há tabela chegando à ordem T. Em código, dbSetOrder(10) é a ordem A.

Data entra com DTOS(). O índice é de texto; o campo data é convertido para AAAAMMDD para ordenar certo. Mais sobre o formato em Tipos de dados em AdvPL.

Mostra Pesq

A documentação da SIX define SHOWPESQ assim: preenchido com S, o índice é mostrado no browse do sistema. Com S, ele entra nas ordens que o usuário escolhe ao pesquisar; com N, continua existindo e funcionando para o código (DbSetOrder, DbOrderNickName), só não é oferecido a quem pesquisa. No padrão há os dois casos — na , as ordens A (B1_FILIAL+B1_BASE3), C (B1_FILIAL+B1_CONTA) e D (B1_FILIAL+B1_CC) são N.

A mesma página traz a regra que pega tabela nova: toda tabela precisa de pelo menos um índice com SHOWPESQ = S para poder ser exibida dentro de um browse. Na ZA1, é o índice 1 que cumpre esse papel.

Na ZA1 desta série, os dois índices ficam visíveis:

OrdemChaveDescriçãoMostra Pesq
1ZA1_FILIAL+ZA1_CODCodigoS
2ZA1_FILIAL+ZA1_NOMENomeS

Onde se cria

Pela documentação da TOTVS, o caminho é o Configurador, em Base de Dados > Dicionário: abra o Dicionário de Dados, localize a tabela, entre em edição, vá em Índices e inclua. No campo da chave, as ações relacionadas oferecem a lista de campos para montar a expressão — filial primeiro. Marque Mostra Pesq se o usuário deve ver o índice e informe o Nickname. Confirme duas vezes, clique em Atualizar Base de Dados e vá avançando até Finalizar — sem esse passo, o índice fica só no que você digitou.

Nickname: por que o índice seu em tabela padrão precisa dele

Suponha que a transportadora desta série criou na SC5 o campo C5_XMOTOR, com o código do motorista do pedido, e quer achar os pedidos de um motorista. O índice novo entra depois dos onze do padrão — digamos, na ordem C. O código natural seria:

ADVPL / TLPP
SC5->(DbSetOrder(12))   // ordem C, hoje

Funciona até a próxima atualização de dicionário. A documentação da TOTVS pede que, antes de rodar um compatibilizador, os índices personalizados estejam identificados pelo nickname: se o compatibilizador precisar criar índices, vai adicioná-los a partir da ordem original instalada pelo Protheus, o que pode sobrescrever índices personalizados sem nickname. A ordem C que era sua passa a ser de um índice do padrão. O DbSetOrder(12) continua compilando e rodando, só que agora num índice com outra chave. O DbSeek não acha o que deveria, ou acha outra coisa, e nenhum erro aparece.

O nickname tira a posição da equação. O índice ganha um nome — ZMOTOR — e o código chama pelo nome:

OrdemChaveNicknameMostra Pesq
(a próxima livre)C5_FILIAL+C5_XMOTOR+C5_NUMZMOTORN

DBOrderNickname(cApelido) seleciona o índice pelo apelido. Se o apelido não existir, a função mostra erro e devolve .F. — o que é bem melhor que pesquisar em silêncio no índice errado:

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} ZPEDMOT
Conta os pedidos de venda de um motorista usando o indice customizado
de nickname ZMOTOR (C5_FILIAL+C5_XMOTOR+C5_NUM), e nao a posicao dele.
@type user function
@param cMotor, character, codigo do motorista (ZA1_COD)
@return numeric, quantidade de pedidos encontrados
/*/
User Function ZPEDMOT(cMotor)

    Local aArea    := GetArea()
    Local aAreaSC5 := {}
    Local cChave   := ""
    Local nQtd     := 0

    DbSelectArea("SC5")
    aAreaSC5 := SC5->(GetArea())

    // A chave precisa ter o tamanho do campo: codigo curto nao casa.
    cChave := xFilial("SC5") + PadR(cMotor, TamSX3("C5_XMOTOR")[1])

    // Pelo nome, nunca pela posicao.
    If SC5->(DbOrderNickName("ZMOTOR"))
        SC5->(DbSeek(cChave))
        While SC5->(!Eof()) .And. SC5->(C5_FILIAL + C5_XMOTOR) == cChave
            nQtd++
            SC5->(DbSkip())
        EndDo
    EndIf

    RestArea(aAreaSC5)
    RestArea(aArea)

Return nQtd

O próprio padrão usa esse desenho — há rotina da TOTVS chamando SB7->(DbOrderNickName("ACDSB701")). O GetArea/RestArea em volta existe porque a função troca a ordem da SC5; quem chamou não pode sentir isso (GetArea e RestArea em AdvPL).

Na tabela customizada (ZA1), não há índice do padrão disputando posição. Ali o nickname é opcional.

Confira no seu ambiente

Os índices de uma tabela, na ordem em que o código os enxerga:

Confira no seu ambienteSQL
SELECT ORDEM, CHAVE, DESCRICAO, NICKNAME, SHOWPESQ, PROPRI
  FROM SIX010
 WHERE INDICE = 'SC5'
   AND D_E_L_E_T_ = ' '
 ORDER BY ORDEM

O sufixo 010 é o da empresa; troque pelo do seu ambiente.

E a consulta que vale rodar antes de qualquer atualização de dicionário: os índices criados pelo cliente que ainda não têm nickname.

Confira no seu ambienteSQL
SELECT INDICE, ORDEM, CHAVE, DESCRICAO
  FROM SIX010
 WHERE PROPRI = 'U'
   AND LTRIM(RTRIM(NICKNAME)) = ''
   AND D_E_L_E_T_ = ' '
 ORDER BY INDICE, ORDEM

Cada linha numa tabela padrão é candidata a nickname — e cada fonte que usa aquele índice por DbSetOrder é candidato a revisão.

Se a sua base tem índice customizado sem nickname e uma atualização pela frente, fale com a gente.

Referências

  1. Central de Atendimentocentraldeatendimento.totvs.com

    Central de Atendimento TOTVS — Como criar índices no ProtheusCaminho de inclusão, Mostra Pesq, nickname, Atualizar Base de Dados e criação física do índice só quando a tabela é aberta.
  2. TDNtdn.totvs.com

    TDN — SIX, Índice das TabelasColunas da SIX, ordem de 1 a 9 e depois letras, e a regra de ao menos um índice com SHOWPESQ = S para a tabela aparecer em browse.
  3. TDNtdn.totvs.com

    TDN — DBOrderNicknameSintaxe DBOrderNickname(cApelido) e retorno .F. quando o apelido não existe.
  4. TDNtdn.totvs.com

    TDN — Atualização de dicionário de dados do ACDOrientação de identificar índices customizados por nickname antes de rodar o compatibilizador.

Continue por aqui