samchan
asked on
BDE - referential integrity and val
It is easy to set tables referential integrity and validation using BDE database desktop. But how does one do it in codes. This will be helpful if tables with their related files such as *.PX, *.VAL are removed/corrupted and needs to be regenerated by the application.
samchan
check out the TUtil stuff they allow you to reindex, pack , fix key violations etc...
I forget the url now but just do a search on DSP
http://SunSITE.icm.edu.pl/delphi/
Later
BoRiS
check out the TUtil stuff they allow you to reindex, pack , fix key violations etc...
I forget the url now but just do a search on DSP
http://SunSITE.icm.edu.pl/delphi/
Later
BoRiS
Listening..
samchan, when you use a proper database engine (I mean something that comes with log facilities ... sqlanywhere, sqlserver, oracle ... and even interbase) you do not need to care with such question. because the database system is almost always able to reconstruct from log. and if you add some backup planning you are almost safe in every circumstances.
I am using SQLAnywhere for several years now, and I never had to reconstruct anything.
When you are using something less robust, let's say BDE or ACCESS, you will sometimes will have to use utilities that will try to put the things back togeather.
I suggest you use another engine, specially if you plan to have many datas in your database.
I consider SQLANYwhere studio as a good buy (if you want to buy something) because you can write java procedures with it. Otherways take Interbase
If You want to stick on BDE, I suggest you get the tools Boris Told you about.
cheers,
Marc
BUT IN NO CASE IT IS YOUR JOB TO WRITE SUCH UTILITIES. Because it is your provider's jub not yours, and because you know nothing about the internal file structures of your database.
I am using SQLAnywhere for several years now, and I never had to reconstruct anything.
When you are using something less robust, let's say BDE or ACCESS, you will sometimes will have to use utilities that will try to put the things back togeather.
I suggest you use another engine, specially if you plan to have many datas in your database.
I consider SQLANYwhere studio as a good buy (if you want to buy something) because you can write java procedures with it. Otherways take Interbase
If You want to stick on BDE, I suggest you get the tools Boris Told you about.
cheers,
Marc
BUT IN NO CASE IT IS YOUR JOB TO WRITE SUCH UTILITIES. Because it is your provider's jub not yours, and because you know nothing about the internal file structures of your database.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you. That's is really a lot of coding. Well, although, I have given you the points, I will be even more happy, if u were to give me some examples on how to use the referential integrity procedure.
hi samchan,
first thanks for accepting,
sample follows, because i've the sample source at home. i will post it in 4-5 hours.
meikl ;-)
first thanks for accepting,
sample follows, because i've the sample source at home. i will post it in 4-5 hours.
meikl ;-)
hi again samchan,
here the sample, how to call.
table1 is a producttable and holds a VendorID, DepartmentID, InventoryID, and a OtherID, pointed to tables, which holds additional informations.
procedure TForm1.Button1Click(Sender : TObject);
begin
AddRI(Table2, Table1, [1], [2], 'RIVendorProduct', RINTRestrict, RINTRestrict,0);
Table2.Close;
AddRI(Table3, Table1, [1], [3], 'RIDepartmentProduct', RINTRestrict, RINTRestrict,0);
Table3.Close;
AddRI(Table4, Table1, [1], [4], 'RIInventoryProduct', RINTRestrict, RINTRestrict,0);
Table4.Close;
AddRI(Table5, Table1, [1], [5], 'RIOtherProduct', RINTRestrict, RINTRestrict,0);
Table2.Open;
Table3.Open;
Table4.Open;
end;
be free to ask for further details
meikl
here the sample, how to call.
table1 is a producttable and holds a VendorID, DepartmentID, InventoryID, and a OtherID, pointed to tables, which holds additional informations.
procedure TForm1.Button1Click(Sender
begin
AddRI(Table2, Table1, [1], [2], 'RIVendorProduct', RINTRestrict, RINTRestrict,0);
Table2.Close;
AddRI(Table3, Table1, [1], [3], 'RIDepartmentProduct', RINTRestrict, RINTRestrict,0);
Table3.Close;
AddRI(Table4, Table1, [1], [4], 'RIInventoryProduct', RINTRestrict, RINTRestrict,0);
Table4.Close;
AddRI(Table5, Table1, [1], [5], 'RIOtherProduct', RINTRestrict, RINTRestrict,0);
Table2.Open;
Table3.Open;
Table4.Open;
end;
be free to ask for further details
meikl
appendix,
you must add the unit bde in the uses-clause.
just for your infoemation
meikl
you must add the unit bde in the uses-clause.
just for your infoemation
meikl
ASKER
Whew! That's really great.
Thank you.
You're really very helpful. You will be on your way to the top of the experts scorer list by continuing giving such fantastic help. Once again, Thank you.
Thank you.
You're really very helpful. You will be on your way to the top of the experts scorer list by continuing giving such fantastic help. Once again, Thank you.
you can find help about all Dbi functions in Delphi help
procedure AddRI(Master, Detail: TTable; RIName: string; ModOp, DelOp: RINTQual);
var
MasterProps, DetailProps: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;
Op: CROpType;
RInt: RINTDesc;
MIndex, DIndex: IDXDesc;
MNo, DNo: Word;
begin
if Master.Active = False then
raise EDatabaseError.Create('Mas
' is not opened');
if Detail.Active = False then
raise EDatabaseError.Create('Det
' is not opened');
if Master.Exclusive = False then
raise EDatabaseError.Create('Tab
' must be opened exclusively');
if Detail.Exclusive = False then
raise EDatabaseError.Create('Tab
' must be opened exclusively');
// Make sure the tables are opened with an index and get their descriptors...
FillChar(DIndex, sizeof(DIndex), 0); FillChar(MIndex, sizeof(MIndex), 0);
Check(DbiGetIndexDesc(Deta
Check(DbiGetIndexDesc(Mast
// Get the table properties to determine table type...
Check(DbiGetCursorProps(Ma
Check(DbiGetCursorProps(De
// If the table is not a Paradox table, raise an error...
if (MasterProps.szTableType <> szPARADOX) and
(MasterProps.szTableType <> szDBASE) then
raise EDatabaseError.Create('Mas
' must be a Paradox or dBASE table type');
if (DetailProps.szTableType <> szPARADOX) and
(DetailProps.szTableType <> szDBASE) then
raise EDatabaseError.Create('Det
' must be a Paradox or dBASE table type');
if MasterProps.szTableType <> DetailProps.szTableType then
raise EDatabaseError.Create('Mas
// Blank out the structures... FillChar(TableDesc, sizeof(TableDesc), 0);
FillChar(RInt, sizeof(RInt), 0);
// Get the database handle from the table's cursor handle...
Check(DbiGetObjFromObj(hDB
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblNa
// Put the table type in the table descriptor...
TableDesc.szTblType := MasterProps.szTableType;
// Set the operation type...
Op := crADD;
TableDesc.pecrRintOp := @Op;
// Set the amount of new RI descriptors...
TableDesc.iRintCount := 1;
// Connect the table descriptor to the RI descriptor...
TableDesc.printDesc := @RInt;
// Setup the RI descriptor...
// Put in the name of the RI...
StrPCopy(RInt.szRintName, RIName);
// Do the restructure on the dependent (detail) table...
RInt.eType := rintDEPENDENT;
// Add the master table name...
StrPCopy(RInt.szTblName, Master.TableName);
// Modify operations will be restricted (this can be changed to rintCASCADE)...
RInt.eModOp := ModOp;
// Delete operations will be restricted (NOTE: rintCASCADE will not work)...
RInt.eDelOp := DelOp;
// Only one field in link...
RInt.iFldCount := 1;
// If the tables are Paradox, then put the associated field numbers in the descriptor...
if (MasterProps.szTableType = szPARADOX) then
begin //
if RInt.eDelOp = rintCASCADE then
raise EDatabaseError.Create('Can
// Put the detail field index in the array...
RInt.aiThisTabFld := DIndex.aiKeyFld;
// Put the master field index in the array...
RInt.aiOthTabFld := MIndex.aiKeyFld; end;
// If the tables are dBASE, then put the sequence number in the descriptor...
if MasterProps.szTableType = szDBASE then
begin
Check(DbiGetIndexSeqNo(Mas
Check(DbiGetIndexSeqNo(Det
// Put the detail field index in the array...
RInt.aiThisTabFld[0] := DNo;
// Put the master field index in the array...
RInt.aiOthTabFld[0] := MNo;
end;
try
Master.Close;
Detail.Close;
Check(DbiDoRestructure(hDb
finally
Master.Open;
Detail.Open;
end;
end;