Subject | Please. A solution with TRANSACTIONS for this problem |
---|---|
Author | pepmallorca |
Post date | 2002-02-01T17:35:25Z |
Hello:
======
I have a problem. I THINK I'M INCOMPATIBLE WITH THE TRANSACTIONS...
I think the better is that I explain what I wan't to do and I hope
someone can help me how to do it.
I wan't to do a program that stores in a table all the words of a
document and the number of ocurrences of each word.
After of that, the user have to see the results in a grid and then
can exit or commit. Only if the user wants the information would
store physical in the table (by default NO)
I need it's go fast, and if it's possible the minimum writes in the
physical database (ONLY the writes that was necessary)... Is possible
all that I need in a program...?
===========
My solution
===========
*** I have a table like this:
CREATE TABLE TEST (ID VARCHAR(6) NOT NULL,
NAME VARCHAR(50) NOT NULL,
NUMB INTEGER,
PRIMARY KEY (ID));
***
*** I have created a procedure like this:
***
CREATE PROCEDURE INS_UPD (PID VARCHAR(6),
PNAME VARCHAR(50))
AS
begin insert into test(id,name,numb) values ( :pId, :pName, 1);
when sqlcode -803 do
update test
set numb=numb+1
where id=:pId;
end
***
*** And my program is this. The bucle is 'like find all the words of
a document'...:
***
I have a component: IB_DATABASE and an IB_QUERY with a GRID to view
the results.
***
*** This is the BUTTON
***
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
vDateIni,vDateFin:TDateTime;
vDateElp:TDateTime;
Hour, Min, Sec, Msec:Word;
begin
vDateIni:=Time;
// if not IB_transaction1.InTransaction
then // //IB_transaction1.starttransaction;
with ib_dsql1 do
begin
sql.text:='';
sql.add('execute procedure ins_upd(:po,:p1)' );
prepare;
end;
for i:=1 to 10000 do
begin
ib_dsql1.Params[0].AsString:=IntToStr(i);
ib_dsql1.Params[1].AsString:=IntToStr(i);
ib_dsql1.execute;
end;
vDateFin:=Time;
vDateElp:=vDateFin - VDateIni;
DecodeTime( vDateElp, Hour, Min, Sec, MSec );
TimeDif.caption := IntToStr( Hour * 60 + Min ) + ' min, ' +
IntToStr( Sec ) + 'seg, ' + IntToStr( MSec )+'
mseg';
// if IB_transaction1.InTransaction then IB_transaction1.commit;
// IB_transaction1.commit;
// IB_database1.commit;
end;
Problems
--------
It works, but sometimes spends 30 secs, sometimes 49 secs...
With i=100000, sometimes 3 min, sometimes 6 min...
It writes continuosly in the disk, and I think there is another way
of do it working more in memory (CacheUpdates... or using
transactions...)
The MAIN PROBLEM is that I don't know how use the TRANSACTIONS in
this problem. I'll try the next: Create an IB_CONNECTION, and a
IB_TRANSACTION, deletes the component IB_DATABASE1 (or not...) and if
I associate the IB_QUERY and the DSQL component to the IB_CONNECTION
and IB_TRANSACTION, I ALWAYS get the 'NICE' message:
* TRANSACTION HAS NO CONNECTIONS *
Someone can helps me?.... if is possibly completing this example...
THANK YOU VERY MUCH,
======
I have a problem. I THINK I'M INCOMPATIBLE WITH THE TRANSACTIONS...
I think the better is that I explain what I wan't to do and I hope
someone can help me how to do it.
I wan't to do a program that stores in a table all the words of a
document and the number of ocurrences of each word.
After of that, the user have to see the results in a grid and then
can exit or commit. Only if the user wants the information would
store physical in the table (by default NO)
I need it's go fast, and if it's possible the minimum writes in the
physical database (ONLY the writes that was necessary)... Is possible
all that I need in a program...?
===========
My solution
===========
*** I have a table like this:
CREATE TABLE TEST (ID VARCHAR(6) NOT NULL,
NAME VARCHAR(50) NOT NULL,
NUMB INTEGER,
PRIMARY KEY (ID));
***
*** I have created a procedure like this:
***
CREATE PROCEDURE INS_UPD (PID VARCHAR(6),
PNAME VARCHAR(50))
AS
begin insert into test(id,name,numb) values ( :pId, :pName, 1);
when sqlcode -803 do
update test
set numb=numb+1
where id=:pId;
end
***
*** And my program is this. The bucle is 'like find all the words of
a document'...:
***
I have a component: IB_DATABASE and an IB_QUERY with a GRID to view
the results.
***
*** This is the BUTTON
***
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
vDateIni,vDateFin:TDateTime;
vDateElp:TDateTime;
Hour, Min, Sec, Msec:Word;
begin
vDateIni:=Time;
// if not IB_transaction1.InTransaction
then // //IB_transaction1.starttransaction;
with ib_dsql1 do
begin
sql.text:='';
sql.add('execute procedure ins_upd(:po,:p1)' );
prepare;
end;
for i:=1 to 10000 do
begin
ib_dsql1.Params[0].AsString:=IntToStr(i);
ib_dsql1.Params[1].AsString:=IntToStr(i);
ib_dsql1.execute;
end;
vDateFin:=Time;
vDateElp:=vDateFin - VDateIni;
DecodeTime( vDateElp, Hour, Min, Sec, MSec );
TimeDif.caption := IntToStr( Hour * 60 + Min ) + ' min, ' +
IntToStr( Sec ) + 'seg, ' + IntToStr( MSec )+'
mseg';
// if IB_transaction1.InTransaction then IB_transaction1.commit;
// IB_transaction1.commit;
// IB_database1.commit;
end;
Problems
--------
It works, but sometimes spends 30 secs, sometimes 49 secs...
With i=100000, sometimes 3 min, sometimes 6 min...
It writes continuosly in the disk, and I think there is another way
of do it working more in memory (CacheUpdates... or using
transactions...)
The MAIN PROBLEM is that I don't know how use the TRANSACTIONS in
this problem. I'll try the next: Create an IB_CONNECTION, and a
IB_TRANSACTION, deletes the component IB_DATABASE1 (or not...) and if
I associate the IB_QUERY and the DSQL component to the IB_CONNECTION
and IB_TRANSACTION, I ALWAYS get the 'NICE' message:
* TRANSACTION HAS NO CONNECTIONS *
Someone can helps me?.... if is possibly completing this example...
THANK YOU VERY MUCH,