SQLMIX e a sintaxe SQL do PostgreSQL
Enviado: 22 Jul 2026 13:35
Olá!
Comecei a fazer por aqui:
Ja fiz upload do estoque, com mudanças dos nomes dos campos, não todos.
fiz alguns ajustes para UTF8, pq dá erro se não olharmos isto. Preferi não mudar o padrão que é UTF8 do DATABASE.
Alguma telas e MSG em Hwgui, eu removi.
O importante é que podemos escrever o SQL, vejam o TEXTO, com espaços e observações, sem nenhum problema para o Harbour e o SQLMIX.
TEXT TO VAR cSQL
...
ENDTEXT
A carga é beeem rápida, pega de 100 em 100 os itens.
Detalhe que essa parte chatinha de ficar colocando as estruturas foi a IA que fez, a IA fez quase 100% dessa função.
Só fiz monitorar, pq sempre tem erros. Coaching de IA
Comecei a fazer por aqui:
Ja fiz upload do estoque, com mudanças dos nomes dos campos, não todos.
fiz alguns ajustes para UTF8, pq dá erro se não olharmos isto. Preferi não mudar o padrão que é UTF8 do DATABASE.
Alguma telas e MSG em Hwgui, eu removi.
O importante é que podemos escrever o SQL, vejam o TEXTO, com espaços e observações, sem nenhum problema para o Harbour e o SQLMIX.
TEXT TO VAR cSQL
...
ENDTEXT
A carga é beeem rápida, pega de 100 em 100 os itens.
Detalhe que essa parte chatinha de ficar colocando as estruturas foi a IA que fez, a IA fez quase 100% dessa função.
Só fiz monitorar, pq sempre tem erros. Coaching de IA
Código: Selecionar todos
#include "dbinfo.ch"
#xcommand TEXT TO VAR <var> => #pragma __stream|<var>:=%s
#xcommand ENDTEXT => #pragma __endtext
Function Main
CriaDbPGSQL()
Return .t.
...
lRet := rddInfo( RDDI_EXECUTE, "DROP TABLE IF EXISTS estoques" )
IF lRet
alert('Apagou a tabela estoques.')
ELSE
alert('Falha apagando a tabela estoques')
RDDINFO(RDDI_DISCONNECT, nCon)
RDDSETDEFAULT( cRdd )
RETURN .T.
ENDIF
...
Function CriaDbPGSQL()
...
Text TO VAR cSQL
CREATE TABLE IF NOT EXISTS estoques (
-- Chave Primária Auto-Incremento (Equivalente ao I:+)
idproduto INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
etc ...
-- Campos Lógicos (Equivalente ao L)
marcado BOOLEAN DEFAULT FALSE,
m2 BOOLEAN DEFAULT FALSE,
m3 BOOLEAN DEFAULT FALSE,
etc ...
-- Campos de Texto de Tamanho Fixo (Códigos e Chaves)
cProd CHAR(20), -- Antigo cod_mercad 13 caractere
gtin CHAR(14), -- Antigo cod_fiscal
codcompart CHAR(20),
idgrupo CHAR(06), -- Antigo cod_grupo
NCM CHAR(08), -- Antigo cod_ncm
etc ...
-- Campos de Texto Variável (Descrições - Otimiza espaço em disco)
xProd VARCHAR(60), -- Antigo mercadoria
grupo VARCHAR(25),
etc ...
-- Campos Numéricos Decimais (Precisão Comercial Exata)
quantidade NUMERIC(14,3) DEFAULT 0.000,
qtdaentreg NUMERIC(14,3) DEFAULT 0.000,
qtd_baixar NUMERIC(14,3) DEFAULT 0.000,
etc ...
-- Campos de Valores Monetários, Custos e Índices
aliqu_icms NUMERIC(06,2) DEFAULT 0.00,
desconto NUMERIC(06,2) DEFAULT 0.00,
etc ...
-- Campos de Data (Equivalente ao D)
validade DATE,
dtapromini DATE,
etc ...
)
ENDTEXT
lRet := rddInfo( RDDI_EXECUTE, cSQL)
IF lRet
alert('Criou a tabela estoques !')
ELSE
alert('Falha na criação da tabela estoques !')
RDDINFO(RDDI_DISCONNECT, nCon)
RDDSETDEFAULT( cRdd )
RETURN .T.
ENDIF
ImportaDbfParaPostgres()
dbUseArea( .T., "SQLMIX" , "select * from estoques",'xx' )
Browse()
ShowEstruturaTabela( 'estoques' )
Return .t.
// --------------------------------------------------------------------------
// Função interna que processa o loop em lotes e atualiza a tela
// --------------------------------------------------------------------------
STATIC PROCEDURE ProcessaMigracao(oDlg, oGauge, oLabel, nTotalReg, nLote)
LOCAL cSqlInsert := ""
LOCAL cValues := ""
LOCAL nContador := 0
LOCAL nProcessados := 0
LOCAL cErroPostgres := ""
dbSelectArea("DBF_EST")
dbGoTop()
DO WHILE !EOF()
nContador++
nProcessados++
// Se for o início de um novo lote, monta o cabeçalho do INSERT
IF nContador == 1
cSqlInsert := "INSERT INTO estoques ( "
cSqlInsert += "marcado, cProd, gtin, codcompart, xProd, quantidade, qtdaentreg, "
etc ...
cSqlInsert += "aluga, status, diamod, digital, enviado ) VALUES "
ENDIF
// Monta a dupla de valores deste registro específico do DBF
cValues := "( "
cValues += SqlVal(DBF_EST->marcado) + ", "
cValues += SqlVal(DBF_EST->cod_mercad) + ", "
cValues += SqlVal(DBF_EST->cod_fiscal) + ", "
cValues += SqlVal(DBF_EST->codcompart) + ", "
cValues += SqlVal(DBF_EST->mercadoria) + ", "
cValues += SqlVal(DBF_EST->quantidade) + ", "
cValues += SqlVal(DBF_EST->qtdaentreg) + ", "
etc ...
cValues += SqlVal(DBF_EST->aluga) + ", "
cValues += SqlVal(DBF_EST->status) + ", "
cValues += SqlVal(DBF_EST->diamod) + ", "
cValues += SqlVal(DBF_EST->digital) + ", "
cValues += SqlVal(DBF_EST->enviado) + " )"
cSqlInsert += cValues
// Se atingiu o tamanho do lote ou chegou ao fim do arquivo
IF nContador == nLote .OR. nProcessados == nTotalReg
// Descarrega o lote inteiro de uma vez no banco
lRet := rddInfo(RDDI_EXECUTE, cSqlInsert)
IF lRet
ELSE
cErroPostgres := rddInfo(RDDI_ERROR)
IF Empty(cErroPostgres)
// Se ainda sumir, tente esta outra constante comum no SQLMix:
// #define RDDI_ERRORMSG 28
cErroPostgres := rddInfo( 28 )
ENDIF
Alert( "Erro no banco de dados: " + cErroPostgres )
alert('Falha na inclusão: ' + str(nProcessados))
hb_memowrit('sql.txt',cSqlInsert)
cancel
exit
ENDIF
nContador := 0 // Reseta o acumulador do lote
ELSE
cSqlInsert += ", " // Adiciona a vírgula para separar a próxima linha/registro
ENDIF
dbSelectArea("DBF_EST")
dbSkip()
ENDDO
dbCloseArea()
alert("Sucesso! Processamento de " + AllTrim(Str(nProcessados)) + " registros concluido.")
RETURN