Usina BRGuía AdvPL
Ingresar
← Todos los temas
FUNDAMENTOPublicado

Desarrollo de queries en Protheus

cQuery → ChangeQuery() → TCQUERY / Embedded SQL | FWPreparedStatement / FWExecStatement → WorkArea

Construye consultas SQL portables y eficientes en Protheus y usa statements parametrizados con FWPreparedStatement y FWExecStatement cuando los valores deban permanecer separados del texto SQL.

SQLDBAccessTopConnQueryRendimientoBase de datosFWExecStatementFWPreparedStatementSetInSQL parametrizado
01 · DESCRIPCIÓN GENERAL

Descripción general

DBAccess sigue siendo la capa de acceso a los bancos SQL homologados, mientras RetSqlName(), GetNextAlias(), ChangeQuery(), TCQUERY y Embedded SQL continúan siendo relevantes. Para queries con valores variables, FWPreparedStatement organiza los parámetros y FWExecStatement permite ejecutar la consulta y abrir el resultado como alias. La documentación oficial también indica que SetIn(), heredado por FWExecStatement desde FWPreparedStatement, se utiliza con cláusulas SQL IN.

02 · SINTAXIS

Sintaxis

cQuery → ChangeQuery() → TCQUERY / Embedded SQL | FWPreparedStatement / FWExecStatement → WorkArea

Parámetros

GetNextAlias()
FunciónOpcional

Genera un alias temporal para el result set y evita colisiones con áreas de trabajo ya abiertas.

RetSqlName()
FunciónOpcional

Convierte el alias lógico de Protheus en el nombre físico de la tabla en la base de datos.

ChangeQuery()
FunciónOpcional

Adapta la instrucción SQL para compatibilidad con las bases homologadas.

TcSetField()
FunciónOpcional

Ajusta los campos no carácter del resultado a los tipos AdvPL esperados.

SqlOrder()
FunciónOpcional

Convierte una expresión de índice AdvPL para utilizarla en una cláusula ORDER BY.

xFilial()
FunciónOpcional

Devuelve la sucursal adecuada para el filtro de la tabla informada.

DToS()
FunciónOpcional

Convierte una fecha a AAAAMMDD cuando ese formato sea necesario al construir la query.

Métodos

FWPreparedStatementClase base para preparar una instrucción SQL con parámetros separados de sus valores.FWPreparedStatement():New( <cQuery> )
FWExecStatementStatement utilizado para ejecutar una query parametrizada y abrir su resultado como alias.FWExecStatement():New( <cQuery> )
SetIn()Completa un parámetro asociado a una cláusula SQL IN. FWExecStatement hereda este método de FWPreparedStatement.oStatement:SetIn( <nParameter>, <aValues> )
03 · EJEMPLO PRÁCTICO

Query básica portable

#Include "TOTVS.ch"
#Include "TopConn.ch"

User Function ExQueryBasica()
    Local cAlias := GetNextAlias()
    Local cQuery := ""

    // RetSqlName() resuelve el nombre físico de la tabla en la base de datos.
    cQuery := "SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1")
    cQuery += " WHERE A1_FILIAL = '" + xFilial("SA1") + "'"
    cQuery += " AND D_E_L_E_T_ = ' '"

    // ChangeQuery() adapta la instrucción a las bases homologadas.
    cQuery := ChangeQuery(cQuery)

    TCQuery cQuery New Alias (cAlias)

    While !(cAlias)->(Eof())
        // A1_NOME significa “Nombre”; conserva sin cambios el identificador real de Protheus.
        ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
        (cAlias)->(DbSkip())
    EndDo

    // Cierra siempre la WorkArea abierta para el result set.
    (cAlias)->(DbCloseArea())
Return
Resultado esperado

La query usa el nombre físico, filtro de sucursal, eliminación lógica, alias dinámico y cierre explícito.

04 · EJEMPLO PRÁCTICO

Query de Recno para posicionar la tabla real

User Function ExQueryRecno()
    Local cAlias := GetNextAlias()
    Local cQuery := ""

    // R_E_C_N_O_ identifica el registro físico representado por la fila del resultado.
    cQuery := "SELECT R_E_C_N_O_ RECNO, A1_COD, A1_NOME FROM " + RetSqlName("SA1")
    cQuery += " WHERE A1_FILIAL = '" + xFilial("SA1") + "'"
    cQuery += " AND D_E_L_E_T_ = ' '"
    cQuery := ChangeQuery(cQuery)

    TCQuery cQuery New Alias (cAlias)

    While !(cAlias)->(Eof())
        DbSelectArea("SA1")
        SA1->(DbGoTo((cAlias)->RECNO))
        // Después de DbGoTo(), SA1 queda posicionada en el registro real. A1_NOME significa “Nombre”.
        ConOut(SA1->A1_COD + " - " + SA1->A1_NOME)
        (cAlias)->(DbSkip())
    EndDo

    (cAlias)->(DbCloseArea())
Return
Resultado esperado

El result set identifica los registros y DbGoTo() posiciona la tabla real mediante R_E_C_N_O_.

05 · EJEMPLO PRÁCTICO

Query parametrizada con FWExecStatement

User Function ExFWExec()
    Local cQuery := ""
    Local cAlias := ""
    Local oStmt

    // El marcador ? mantiene el valor fuera del texto SQL.
    cQuery := "SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1")
    cQuery += " WHERE A1_FILIAL = ? AND D_E_L_E_T_ = ' '"
    cQuery := ChangeQuery(cQuery)

    oStmt := FWExecStatement():New(cQuery)
    oStmt:SetString(1, xFilial("SA1"))
    cAlias := oStmt:OpenAlias()

    While !(cAlias)->(Eof())
        // A1_NOME significa “Nombre”; conserva sin cambios el identificador real de Protheus.
        ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
        (cAlias)->(DbSkip())
    EndDo

    (cAlias)->(DbCloseArea())
    oStmt:Destroy()
Return
Resultado esperado

La query parametriza la sucursal, abre el resultado como alias y libera los recursos explícitamente.

06 · EJEMPLO PRÁCTICO

Cláusula IN con SetIn()

User Function ExSetIn()
    Local cQuery := ""
    Local cAlias := ""
    Local aClientes := {"000010", "000020", "000030"}
    Local oStmt

    // El segundo marcador representa la lista usada por la cláusula IN.
    cQuery := "SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1")
    cQuery += " WHERE A1_FILIAL = ? AND A1_COD IN (?) AND D_E_L_E_T_ = ' '"
    cQuery := ChangeQuery(cQuery)

    oStmt := FWExecStatement():New(cQuery)
    oStmt:SetString(1, xFilial("SA1"))
    oStmt:SetIn(2, aClientes)
    cAlias := oStmt:OpenAlias()

    While !(cAlias)->(Eof())
        ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
        (cAlias)->(DbSkip())
    EndDo

    (cAlias)->(DbCloseArea())
    oStmt:Destroy()
Return
Resultado esperado

SetIn() asocia un array con el marcador de la cláusula IN.

BUENAS PRÁCTICAS
  • Selecciona solo las columnas necesarias; evita SELECT *.
  • Utiliza GetNextAlias() en lugar de alias fijos.
  • Utiliza RetSqlName() y pasa la instrucción por ChangeQuery().
  • Filtra cada filial con xFilial() de su tabla.
  • Excluye registros eliminados lógicamente en todas las tablas.
  • Prefiere JOIN en sintaxis ANSI.
  • Utiliza funciones de agregación para reducir filas cuando corresponda.
  • Cierra siempre la WorkArea con DbCloseArea().
  • Considera el rendimiento como resultado conjunto del código AdvPL, DBAccess, SGBD, infraestructura y volumen; mide las consultas lentas antes de cambiar índices o hardware.
  • Documenta los índices personalizados y revísalos después de actualizar Protheus.
  • Define archivo y retención con requisitos de negocio, legales, de copia y recuperación.
  • Obtén las tablas físicas con RetSqlName() y el contexto de filial con xFilial(); no deduzcas sufijos por empresa o filial.
  • Mantén la estructura del banco alineada con el diccionario de Protheus y utiliza mecanismos admitidos por TOTVS para cambios estructurales.
  • Confirma los tipos reales del resultado: fechas tradicionales y valores vacíos pueden usar caracteres, espacios o cero en lugar de NULL.
  • Prefiere la parametrización cuando los valores variables puedan mantenerse separados de la estructura SQL.
  • Mantén RetSqlName(), xFilial() y el tratamiento de D_E_L_E_T_ de acuerdo con la tabla y el objetivo de la query.
  • Cierra el alias retornado por OpenAlias() y destruye el statement al finalizar el procesamiento.
ERRORES COMUNES
  • Los campos de control de DBAccess representan registros y exclusiones lógicas.
  • No supongas que el resultado admite la misma navegación de una tabla ISAM.
  • El SQL específico de un banco puede fallar en los demás.
  • Los campos no agregados deben ser compatibles con GROUP BY.
  • Utiliza queries de Recno solo cuando necesites posicionar la tabla real.
  • Nunca concatenes entradas no confiables directamente en SQL.
  • No deshabilites ni elimines índices estándar de Protheus sin orientación formal de TOTVS, revisión de un DBA, homologación y plan de reversión.
  • No apliques FILLFACTOR, reconstrucción de índices ni cambios de estadísticas globalmente; mide cada carga.
  • El artículo citado relata experiencia práctica con SQL Server en un contexto histórico de Protheus. No es documentación oficial de TOTVS ni se aplica automáticamente a otros bancos o versiones.
  • No crees campos, tablas, constraints o índices sin evaluar el diccionario, la compatibilidad con DBAccess y el proceso oficial de actualización.
  • Particionado, compresión, replicación, clúster e In-Memory dependen de las versiones actuales del SGBD, Protheus y DBAccess. Las afirmaciones de 2012 son contexto histórico, no reglas actuales.
  • No trates FWExecStatement como sustituto automático de cualquier query; elige la técnica según el contexto, la portabilidad y la necesidad de parametrización.
  • La posición informada en SetString(), SetIn() y métodos equivalentes debe coincidir con el orden de los marcadores de la instrucción.
  • Evita concatenar directamente valores externos o proporcionados por el usuario en el texto SQL cuando puedas parametrizarlos.

Contenido relacionado

REFERENCIAS
  1. TOTVS. Desarrollo de queries en Protheus. TDN.
  2. TOTVS. Embedded SQL. TDN.
  3. TOTVS. Comando TCQUERY. TDN.
  4. LIMA, Fabrício. 5 motivos para que quienes utilizan Protheus (TOTVS) contraten un DBA SQL Server. Blog, publicado el 14 dic. 2013, con actualizaciones posteriores. Referencia práctica complementaria; no es documentación oficial de TOTVS.
  5. INOWE, Marcel. Consejos sobre la base de datos de Protheus (TOTVS). 4SQLServer, 12 sep. 2012. Referencia práctica e histórica sobre SQL Server; los comentarios originales registran correcciones y cambios posteriores.
  6. MICROSIGA. Programación ADVPL — Uso de Query. Documentación oficial histórica Programación ADVPL X SQL, 27 ago. 2006. Sección "Particularidades Protheus".
  7. MICROSIGA. Manual de Programación. Documento colaborativo, archivo fechado el 11 jul. 2001. Referencia histórica.
  8. TOTVS. FWExecStatement. TDN.
  9. TOTVS. FWPreparedStatement. TDN.
  10. TOTVS. Cross Segmentos — ADVPL — FwExecStatement — SetIn. Central de Atendimento.
Estado
Publicado
Página creada el
Última revisión el
Idioma original
Portugués
Revisión
Usina.BR
0 comentario(s) aprobado(s)

Comentarios

Todavía no hay comentarios aprobados.

Inicia sesión con Google o Microsoft para comentar.

Desarrollado con Usina Docs · Alpha