Page 1 of 1
MariaDB doubt about field
Posted: Sat Mar 09, 2019 3:11 am
by wartiaga
Hi guys,
I have a dbf table that contains a field that controls the next number of an invoice for example. I block the registry, get the value, use, increase one, save the new value and unlock. How I do this control with mariadb? Field auto increment does not work because I want to have the option to change the value at any time.
Thanks in advance.
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 3:33 am
by nageswaragunupudi
You can do exactly the same thing in MariaDB also.
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 2:05 pm
by wartiaga
nageswaragunupudi wrote:You can do exactly the same thing in MariaDB also.
Thank you Nages! Can you provide a sample to work with no problems in lan enviroment? I try using fivewin native mariadb functions/commands. I new in mariadb.
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 4:32 pm
by carlos vargas
Here, i get the next counter value at save the data.
Code: Select all
FUNCTION IncCount( cTable, cField )
LOCAL oQryTmp
LOCAL nCount := 0
oQryTmp := oServer:Query( "SELECT " + cField + " FROM " + cTable + " FOR UPDATE" )
IF oQryTmp:RecCount() >= 0
nCount := oQryTmp:FieldGet( 1 ) + 1
oServer:Execute( "UPDATE " + cTable + " SET " + cField + " = " + Var2Str( nCount ) )
ENDIF
oQryTmp:End()
RETURN nCount
Code: Select all
STATIC PROCEDURE NuevoPrestamo_Grabar()
LOCAL i, cSqlDetalle := "INSERT INTO prestamosdet (num_pres,cuota_no,fecha_prog,valor_prog,estado) VALUES "
LOCAL lGrabado := FALSE
FOR i:=1 TO Len( aTabla )
cSqlDetalle += "( &1, " + Var2Str( aTabla[ i, TABLA_ABO_NO ] ) + "," + ;
Var2Str( aTabla[ i, TABLA_ABO_FECHA ] ) + "," + ;
Var2Str( aTabla[ i, TABLA_ABO_VALPROG ] ) + "," + "'A'),"
NEXT
cSqlDetalle := HB_StrShrink( cSqlDetalle )
oServer:lThrowError := TRUE
TRY
oServer:BeginTransaction()
IF ( nPresNum := IncCount( "control", "cont_pres" ) ) > 0
oServer:Insert2( "prestamosmas", { { "num_ruta" , nRutaCob }, ;
{ "num_clie" , nClieNum }, ; /*datos de cliente*/
{ "nombre" , cClieNom }, ;
{ "cedula" , cClieCed }, ;
{ "ciudad" , cClieCiu }, ;
{ "direccion" , cClieDir }, ;
{ "telefonos" , cClieTel }, ;
{ "num_pres" , nPresNum }, ; /*datos del prestamo*/
{ "importe" , nImporte }, ;
{ "interes" , nInteres }, ;
{ "cuotas" , nCuotas }, ;
{ "modalidad_pago", nModalidad }, ;
{ "valor_cuota" , nValorCuota }, ;
{ "total" , nTotal }, ;
{ "fecha_ent" , dFechaEnt }, ;
{ "fecha_ini" , dFechaIni }, ;
{ "fecha_fin" , dFechaFin }, ;
{ "abonado" , 0 }, ;
{ "estado" , "A" }, ;
{ "nota" , cNota } } )
oServer:Execute( cSqlDetalle, { nPresNum } )
ENDIF
oServer:Commit()
lGrabado := TRUE
CATCH oError
ShowError( oError )
oServer:Rollback()
END
oServer:lThrowError := FALSE
IF lGrabado
NuevoPrestamo_MostrarNumero()
IF MsgNoYes( "Desea imprimir contrato del prestamo?" )
NuevoPrestamo_Imprimir()
ENDIF
NuevoPrestamo_Limpiar1( TRUE )
oDlgE:Update()
oBtnSearch:SetFocus()
ENDIF
RETURN lGrabado
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 6:56 pm
by wartiaga
carlos vargas wrote:Here, i get the next counter value at save the data.
Code: Select all
FUNCTION IncCount( cTable, cField )
LOCAL oQryTmp
LOCAL nCount := 0
oQryTmp := oServer:Query( "SELECT " + cField + " FROM " + cTable + " FOR UPDATE" )
IF oQryTmp:RecCount() >= 0
nCount := oQryTmp:FieldGet( 1 ) + 1
oServer:Execute( "UPDATE " + cTable + " SET " + cField + " = " + Var2Str( nCount ) )
ENDIF
oQryTmp:End()
RETURN nCount
Code: Select all
STATIC PROCEDURE NuevoPrestamo_Grabar()
LOCAL i, cSqlDetalle := "INSERT INTO prestamosdet (num_pres,cuota_no,fecha_prog,valor_prog,estado) VALUES "
LOCAL lGrabado := FALSE
FOR i:=1 TO Len( aTabla )
cSqlDetalle += "( &1, " + Var2Str( aTabla[ i, TABLA_ABO_NO ] ) + "," + ;
Var2Str( aTabla[ i, TABLA_ABO_FECHA ] ) + "," + ;
Var2Str( aTabla[ i, TABLA_ABO_VALPROG ] ) + "," + "'A'),"
NEXT
cSqlDetalle := HB_StrShrink( cSqlDetalle )
oServer:lThrowError := TRUE
TRY
oServer:BeginTransaction()
IF ( nPresNum := IncCount( "control", "cont_pres" ) ) > 0
oServer:Insert2( "prestamosmas", { { "num_ruta" , nRutaCob }, ;
{ "num_clie" , nClieNum }, ; /*datos de cliente*/
{ "nombre" , cClieNom }, ;
{ "cedula" , cClieCed }, ;
{ "ciudad" , cClieCiu }, ;
{ "direccion" , cClieDir }, ;
{ "telefonos" , cClieTel }, ;
{ "num_pres" , nPresNum }, ; /*datos del prestamo*/
{ "importe" , nImporte }, ;
{ "interes" , nInteres }, ;
{ "cuotas" , nCuotas }, ;
{ "modalidad_pago", nModalidad }, ;
{ "valor_cuota" , nValorCuota }, ;
{ "total" , nTotal }, ;
{ "fecha_ent" , dFechaEnt }, ;
{ "fecha_ini" , dFechaIni }, ;
{ "fecha_fin" , dFechaFin }, ;
{ "abonado" , 0 }, ;
{ "estado" , "A" }, ;
{ "nota" , cNota } } )
oServer:Execute( cSqlDetalle, { nPresNum } )
ENDIF
oServer:Commit()
lGrabado := TRUE
CATCH oError
ShowError( oError )
oServer:Rollback()
END
oServer:lThrowError := FALSE
IF lGrabado
NuevoPrestamo_MostrarNumero()
IF MsgNoYes( "Desea imprimir contrato del prestamo?" )
NuevoPrestamo_Imprimir()
ENDIF
NuevoPrestamo_Limpiar1( TRUE )
oDlgE:Update()
oBtnSearch:SetFocus()
ENDIF
RETURN lGrabado
Thank you Carlos but no need to block and unblock the field like dbf table in lan enviroment?
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 7:04 pm
by nageswaragunupudi
Thank you Carlos but no need to block and unblock the field like dbf table in lan enviroment?
SELECT ... FOR UPDATE
locks the record.
Re: MariaDB doubt about field
Posted: Sat Mar 09, 2019 7:42 pm
by wartiaga
nageswaragunupudi wrote:Thank you Carlos but no need to block and unblock the field like dbf table in lan enviroment?
SELECT ... FOR UPDATE
locks the record.
Thank you Nages in this case I need to treat the select return before save?
Re: MariaDB doubt about field
Posted: Sun Mar 10, 2019 5:24 pm
by nageswaragunupudi
You may use Mr. Carlos' function IncCount() with suitable modifications.
Alernatively, I prefer a function using a different approach.
Code: Select all
function seq_nextval( cName )
oCn:Execute( "UPDATE sequences SET seq_value = LAST_INSERT_ID( seq_value + 1 )" + ;
" WHERE seq_name = '" + cName + "';" + ;
"SELECT LAST_INSERT_ID()" )
return oCn:aNext[ 1, 1, 1 ]
where the table `sequences` maintains sequential ids for different tables.
This function also is network-safe (multi-user).
This is a small example using this function to maintain `id` of table `test_seq`.
Code: Select all
#include "fivewin.ch"
static oCn
//----------------------------------------------------------------------------//
function Main()
local oRs, nID
SET DATE ITALIAN
SET CENTURY ON
SET TIME FORMAT TO "HH:MM:SS"
oCn := FW_DemoDB()
// oCn:DropTable( "test_seq" )
// oCn:DropTable( "sequences" )
CheckTables()
XBROWSER oCn:test_seq FASTEDIT
oCn:Close()
return nil
//----------------------------------------------------------------------------//
function test_seq_rsedit( oRec )
local oDlg, oFont
if oRec:RecNo == 0 // new record
oRec:id := seq_nextval( "test_seq" )
endif
DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
DEFINE DIALOG oDlg SIZE 400,240 PIXEL TRUEPIXEL FONT oFont ;
TITLE If( oRec:RecNo == 0, "NEW", "EDIT" )
oDlg:bInit := <||
@ 40, 30 SAY "ID :" GET oRec:ID SIZE 100,24 PIXEL PICTURE "999999" READONLY
@ 70, 30 SAY "Name :" GET oRec:Name SIZE 300,24 PIXEL
@ 100, 30 SAY "City :" GET oRec:City SIZE 300,24 PIXEL
return nil
>
@ 160, 30 BTNBMP PROMPT "SAVE" SIZE 100,40 PIXEL OF oDlg FLAT ;
ACTION ( oRec:Save(), oDlg:End() )
@ 160,270 BTNBMP PROMPT "CANCEL" SIZE 100,40 PIXEL OF oDlg FLAT ;
ACTION ( oDlg:End() )
ACTIVATE DIALOG oDlg CENTERED ON PAINT oDlg:Box( 20, 10, 150, 390 )
RELEASE FONT oFont
return nil
//----------------------------------------------------------------------------//
function CheckTables()
local nID
if !oCn:TableExists( "test_seq" )
oCn:CreateTable( "test_seq", { { "id", "N", 6, 0, "PRI" }, ;
{ "name", "C", 40, 0 }, ;
{ "city", "C", 40, 0 }, ;
{ "upddt","=", 8, 0 } } )
endif
nID := oCn:QueryResult( "SELECT MAX( id ) FROM test_seq" )
if !oCn:TableExists( "sequences" )
oCn:CreateTable( "sequences", { { "seq_name", "C", 64, 0, "PRI" }, ;
{ "seq_value", "N", 6, 0 } } )
oCn:Insert( "sequences", "seq_name,seq_value", { "test_seq", nID } )
endif
return nil
//----------------------------------------------------------------------------//
function seq_nextval( cName )
oCn:Execute( "UPDATE sequences SET seq_value = LAST_INSERT_ID( seq_value + 1 )" + ;
" WHERE seq_name = '" + cName + "';" + ;
"SELECT LAST_INSERT_ID()" )
return oCn:aNext[ 1, 1, 1 ]
//----------------------------------------------------------------------------//
You may copy this code to \fwh\samples folder and use buildh.bat or buildx.bat to build and run.
Note: The names "sequence" and "nextval()" are adapted from Oracle with the same functionality.
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 7:30 am
by Horizon
Hi Mr. Rao,
Everytime press + and cancel button id is incremented by 1. Is there any solution to increment when press cancel button?
Thanks.
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 7:33 am
by nageswaragunupudi
Do you want to increment when pressing cancel button? why?
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 8:25 am
by Horizon
Pardon mr. Rao.
I mean not to increment.
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 8:53 am
by nageswaragunupudi
There are two options.
1) Increment the id when a new record is saved. The most common solution for this is to Auto Increment field.
This is what most users use.
In this case, we know the new ID only when the record is saved, not before that. So, while editing a new record, we do not know the new ID that will be finally saved.
2) Decide the new ID in advance and display while editing a new record and save the same ID. This is not what many programmers prefer. The above solution is for those who want this option for whatever reasons.
What you want is easily done by using the auto-increment field and most examples we posted use that method. To check the behaviour, please build and run this small test
Code: Select all
#include "fivewin.ch"
function Main()
local oCn := FW_DemoDB()
XBROWSER oCn:customer FASTEDIT
oCn:Close()
return nil
You may just ignore the methods suggested in this post.
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 12:59 pm
by wartiaga
nageswaragunupudi wrote:You may use Mr. Carlos' function IncCount() with suitable modifications.
Alernatively, I prefer a function using a different approach.
Code: Select all
function seq_nextval( cName )
oCn:Execute( "UPDATE sequences SET seq_value = LAST_INSERT_ID( seq_value + 1 )" + ;
" WHERE seq_name = '" + cName + "';" + ;
"SELECT LAST_INSERT_ID()" )
return oCn:aNext[ 1, 1, 1 ]
where the table `sequences` maintains sequential ids for different tables.
This function also is network-safe (multi-user).
This is a small example using this function to maintain `id` of table `test_seq`.
Code: Select all
#include "fivewin.ch"
static oCn
//----------------------------------------------------------------------------//
function Main()
local oRs, nID
SET DATE ITALIAN
SET CENTURY ON
SET TIME FORMAT TO "HH:MM:SS"
oCn := FW_DemoDB()
// oCn:DropTable( "test_seq" )
// oCn:DropTable( "sequences" )
CheckTables()
XBROWSER oCn:test_seq FASTEDIT
oCn:Close()
return nil
//----------------------------------------------------------------------------//
function test_seq_rsedit( oRec )
local oDlg, oFont
if oRec:RecNo == 0 // new record
oRec:id := seq_nextval( "test_seq" )
endif
DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
DEFINE DIALOG oDlg SIZE 400,240 PIXEL TRUEPIXEL FONT oFont ;
TITLE If( oRec:RecNo == 0, "NEW", "EDIT" )
oDlg:bInit := <||
@ 40, 30 SAY "ID :" GET oRec:ID SIZE 100,24 PIXEL PICTURE "999999" READONLY
@ 70, 30 SAY "Name :" GET oRec:Name SIZE 300,24 PIXEL
@ 100, 30 SAY "City :" GET oRec:City SIZE 300,24 PIXEL
return nil
>
@ 160, 30 BTNBMP PROMPT "SAVE" SIZE 100,40 PIXEL OF oDlg FLAT ;
ACTION ( oRec:Save(), oDlg:End() )
@ 160,270 BTNBMP PROMPT "CANCEL" SIZE 100,40 PIXEL OF oDlg FLAT ;
ACTION ( oDlg:End() )
ACTIVATE DIALOG oDlg CENTERED ON PAINT oDlg:Box( 20, 10, 150, 390 )
RELEASE FONT oFont
return nil
//----------------------------------------------------------------------------//
function CheckTables()
local nID
if !oCn:TableExists( "test_seq" )
oCn:CreateTable( "test_seq", { { "id", "N", 6, 0, "PRI" }, ;
{ "name", "C", 40, 0 }, ;
{ "city", "C", 40, 0 }, ;
{ "upddt","=", 8, 0 } } )
endif
nID := oCn:QueryResult( "SELECT MAX( id ) FROM test_seq" )
if !oCn:TableExists( "sequences" )
oCn:CreateTable( "sequences", { { "seq_name", "C", 64, 0, "PRI" }, ;
{ "seq_value", "N", 6, 0 } } )
oCn:Insert( "sequences", "seq_name,seq_value", { "test_seq", nID } )
endif
return nil
//----------------------------------------------------------------------------//
function seq_nextval( cName )
oCn:Execute( "UPDATE sequences SET seq_value = LAST_INSERT_ID( seq_value + 1 )" + ;
" WHERE seq_name = '" + cName + "';" + ;
"SELECT LAST_INSERT_ID()" )
return oCn:aNext[ 1, 1, 1 ]
//----------------------------------------------------------------------------//
You may copy this code to \fwh\samples folder and use buildh.bat or buildx.bat to build and run.
Note: The names "sequence" and "nextval()" are adapted from Oracle with the same functionality.
Thank you Mr. Nages.
Re: MariaDB doubt about field
Posted: Mon Mar 11, 2019 1:40 pm
by Horizon
nageswaragunupudi wrote:There are two options.
1) Increment the id when a new record is saved. The most common solution for this is to Auto Increment field.
This is what most users use.
In this case, we know the new ID only when the record is saved, not before that. So, while editing a new record, we do not know the new ID that will be finally saved.
2) Decide the new ID in advance and display while editing a new record and save the same ID. This is not what many programmers prefer. The above solution is for those who want this option for whatever reasons.
What you want is easily done by using the auto-increment field and most examples we posted use that method. To check the behaviour, please build and run this small test
Code: Select all
#include "fivewin.ch"
function Main()
local oCn := FW_DemoDB()
XBROWSER oCn:customer FASTEDIT
oCn:Close()
return nil
You may just ignore the methods suggested in this post.
Thank you for clarification Mr. Rao.