GetNextAlias()Generates a temporary alias for the result set and avoids collisions with already open work areas.
AdvPL GuidecQuery → ChangeQuery() → TCQUERY / Embedded SQL | FWPreparedStatement / FWExecStatement → WorkAreaBuild portable and efficient SQL queries in Protheus and use parameterized statements with FWPreparedStatement and FWExecStatement when values should remain separate from SQL text.
DBAccess remains the access layer for supported SQL databases, while RetSqlName(), GetNextAlias(), ChangeQuery(), TCQUERY, and Embedded SQL remain relevant. For queries with changing values, FWPreparedStatement organizes statement parameters and FWExecStatement can execute the query and open the result as an alias. Official TOTVS documentation also states that SetIn(), inherited by FWExecStatement from FWPreparedStatement, is used with SQL IN clauses.
cQuery → ChangeQuery() → TCQUERY / Embedded SQL | FWPreparedStatement / FWExecStatement → WorkAreaGetNextAlias()Generates a temporary alias for the result set and avoids collisions with already open work areas.
RetSqlName()Converts the logical Protheus alias into the physical table name in the database.
ChangeQuery()Adapts the SQL statement for compatibility with supported databases.
TcSetField()Adjusts non-character result fields to the expected AdvPL types.
SqlOrder()Converts an AdvPL index expression for use in an ORDER BY clause.
xFilial()Returns the appropriate branch value for the specified table filter.
DToS()Converts a date to YYYYMMDD when that format is required while building the query.
FWPreparedStatement():New( <cQuery> )FWExecStatement():New( <cQuery> )oStatement:SetIn( <nParameter>, <aValues> )#Include "TOTVS.ch"
#Include "TopConn.ch"
User Function ExQueryBasic()
Local cAlias := GetNextAlias()
Local cQuery := ""
// RetSqlName() resolves the physical table name in the database.
cQuery := "SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1")
cQuery += " WHERE A1_FILIAL = '" + xFilial("SA1") + "'"
cQuery += " AND D_E_L_E_T_ = ' '"
// ChangeQuery() adapts the statement to supported databases.
cQuery := ChangeQuery(cQuery)
TCQuery cQuery New Alias (cAlias)
While !(cAlias)->(Eof())
// A1_NOME means “Name”; keep the actual Protheus field identifier unchanged.
ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
(cAlias)->(DbSkip())
EndDo
// Always close the WorkArea opened for the result set.
(cAlias)->(DbCloseArea())
ReturnThe query uses the physical table name, branch filter, logical-deletion filter, dynamic alias, and explicit cleanup.
User Function ExQueryRecno()
Local cAlias := GetNextAlias()
Local cQuery := ""
// R_E_C_N_O_ identifies the physical record represented by the result row.
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))
// After DbGoTo(), SA1 is positioned on the real record. A1_NOME means “Name”.
ConOut(SA1->A1_COD + " - " + SA1->A1_NOME)
(cAlias)->(DbSkip())
EndDo
(cAlias)->(DbCloseArea())
ReturnThe result set identifies records and DbGoTo() positions the real table using R_E_C_N_O_.
User Function ExFWExec()
Local cQuery := ""
Local cAlias := ""
Local oStmt
// The ? placeholder keeps the value outside the SQL text.
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 means “Name”; keep the real Protheus identifier unchanged.
ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
(cAlias)->(DbSkip())
EndDo
(cAlias)->(DbCloseArea())
oStmt:Destroy()
ReturnThe query parameterizes the branch, opens the result as an alias, and explicitly releases resources.
User Function ExSetIn()
Local cQuery := ""
Local cAlias := ""
Local aCustomers := {"000010", "000020", "000030"}
Local oStmt
// The second placeholder represents the list used by the IN clause.
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, aCustomers)
cAlias := oStmt:OpenAlias()
While !(cAlias)->(Eof())
ConOut((cAlias)->A1_COD + " - " + (cAlias)->A1_NOME)
(cAlias)->(DbSkip())
EndDo
(cAlias)->(DbCloseArea())
oStmt:Destroy()
ReturnSetIn() associates an array with the IN-clause placeholder.
© 2026 Usina.BR. All rights reserved. TOTVS, Protheus, Microsiga and their respective logos are trademarks of their owners. AdvPL Guide is independent and uses limited, attributed excerpts justified by educational purposes. See the Terms of Use. Terms of Use
Comments
There are no approved comments yet.
Sign in with Google or Microsoft to comment.