skeleton
asked on
Converting auto-increment fields to integer
How can you convert (change) a auto-increment field to a integer field and visa versa at run time without destroying the existing data (integer values)?
What DB are you using?
Rob ;-)
Rob ;-)
ASKER
Sorry, for Paradox!
hi skeleton,
vice versa is not possible,
only the direction autoinc->integer
my test-unit
unit db_res_ainc_u;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, StdCtrls, bde;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Table1: TTable;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//pasted from borland - BDE-API sample
Type
ChangeRec = packed record
szName: DBINAME;
iType: word;
iSubType: word;
iLength: word;
iPrecision: byte;
end;
procedure ChangeField(Table: TTable; Field: TField; Rec: ChangeRec);
var
Props: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;
pFields: pFLDDesc;
pOp: pCROpType;
B: byte;
begin
// Initialize the pointers...
pFields := nil; pOp := nil;
// Make sure the table is open exclusively so we can get the db handle...
if Table.Active = False then
raise EDatabaseError.Create('Tab le must be opened to restructure');
if Table.Exclusive = False then
raise EDatabaseError.Create('Tab le must be opened exclusively to restructure');
Check(DbiSetProp(hDBIObj(T able.Handl e), curxltMODE, integer(xltNONE)));
// Get the table properties to determine table type...
Check(DbiGetCursorProps(Ta ble.Handle , Props));
// Make sure the table is either Paradox or dBASE...
if (Props.szTableType <> szPARADOX) and (Props.szTableType <> szDBASE) then
raise EDatabaseError.Create('Fie ld altering can only occur on Paradox' +
' or dBASE tables');
// Allocate memory for the field descriptor...
pFields := AllocMem(Table.FieldCount * sizeof(FLDDesc));
// Allocate memory for the operation descriptor...
pOp := AllocMem(Table.FieldCount * sizeof(CROpType));
try
// Set the pointer to the index in the operation descriptor to put
// crMODIFY (This means a modification to the record is going to happen)...
Inc(pOp, Field.Index);
pOp^ := crMODIFY;
Dec(pOp, Field.Index);
// Fill the field descriptor with the existing field information...
Check(DbiGetFieldDescs(Tab le.Handle, pFields));
// Set the pointer to the index in the field descriptor to make the
// midifications to the field
Inc(pFields, Field.Index);
// If the szName portion of the ChangeRec has something in it, change it...
if StrLen(Rec.szName) > 0 then
pFields^.szName := Rec.szName;
// If the iType portion of the ChangeRec has something in it, change it...
if Rec.iType > 0 then
pFields^.iFldType := Rec.iType;
// If the iSubType portion of the ChangeRec has something in it, change it...
if Rec.iSubType > 0 then
pFields^.iSubType := Rec.iSubType;
// If the iLength portion of the ChangeRec has something in it, change it...
if Rec.iLength > 0 then
pFields^.iUnits1 := Rec.iLength;
// If the iPrecision portion of the ChangeRec has something in it, change it...
if Rec.iPrecision > 0 then
pFields^.iUnits2 := Rec.iPrecision;
Dec(pFields, Field.Index);
for B := 1 to Table.FieldCount do begin
pFields^.iFldNum := B;
Inc(pFields, 1);
end;
Dec(pFields, Table.FieldCount);
// Blank out the structure...
FillChar(TableDesc, sizeof(TableDesc), 0);
// Get the database handle from the table's cursor handle...
Check(DbiGetObjFromObj(hDB IObj(Table .Handle), objDATABASE, hDBIObj(hDb)));
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblNa me, Table.TableName);
// Put the table type in the table descriptor...
StrPCopy(TableDesc.szTblTy pe, Props.szTableType);
// The following three lines are necessary when doing any field restructure
// operations on a table...
// Set the field count for the table
TableDesc.iFldCount := Table.FieldCount;
// Link the operation descriptor to the table descriptor...
TableDesc.pecrFldOp := pOp;
// Link the field descriptor to the table descriptor...
TableDesc.pFldDesc := pFields;
// Close the table so the restructure can complete...
Table.Close;
// Call DbiDoRestructure...
Check(DbiDoRestructure(hDb , 1, @TableDesc, nil, nil, nil, FALSE));
finally
if pFields <> nil then
FreeMem(pFields);
if pOp <> nil then
FreeMem(pOp);
end;
end;
//autoInc->Integer
procedure TForm1.Button1Click(Sender : TObject);
var CR : ChangeRec;
begin
Table1.Close;
Table1.Exclusive := True;
Table1.Open;
FillChar(CR,SizeOf(CR),0);
CR.iType := fldINT32;
ChangeField(Table1,Table1. FieldbyNam e('ID'),CR );
Table1.Close;
end;
//integer->autoinc, does not work, if table is not empty
procedure TForm1.Button2Click(Sender : TObject);
var CR : ChangeRec;
begin
Table1.Close;
Table1.Exclusive := True;
Table1.Open;
FillChar(CR,SizeOf(CR),0);
CR.iType := fldPDXAUTOINC; //works only if table empty
ChangeField(Table1,Table1. FieldbyNam e('ID'),CR );
Table1.Close;
end;
end.
try it out
meikl ;-)
vice versa is not possible,
only the direction autoinc->integer
my test-unit
unit db_res_ainc_u;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, StdCtrls, bde;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Table1: TTable;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//pasted from borland - BDE-API sample
Type
ChangeRec = packed record
szName: DBINAME;
iType: word;
iSubType: word;
iLength: word;
iPrecision: byte;
end;
procedure ChangeField(Table: TTable; Field: TField; Rec: ChangeRec);
var
Props: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;
pFields: pFLDDesc;
pOp: pCROpType;
B: byte;
begin
// Initialize the pointers...
pFields := nil; pOp := nil;
// Make sure the table is open exclusively so we can get the db handle...
if Table.Active = False then
raise EDatabaseError.Create('Tab
if Table.Exclusive = False then
raise EDatabaseError.Create('Tab
Check(DbiSetProp(hDBIObj(T
// Get the table properties to determine table type...
Check(DbiGetCursorProps(Ta
// Make sure the table is either Paradox or dBASE...
if (Props.szTableType <> szPARADOX) and (Props.szTableType <> szDBASE) then
raise EDatabaseError.Create('Fie
' or dBASE tables');
// Allocate memory for the field descriptor...
pFields := AllocMem(Table.FieldCount * sizeof(FLDDesc));
// Allocate memory for the operation descriptor...
pOp := AllocMem(Table.FieldCount * sizeof(CROpType));
try
// Set the pointer to the index in the operation descriptor to put
// crMODIFY (This means a modification to the record is going to happen)...
Inc(pOp, Field.Index);
pOp^ := crMODIFY;
Dec(pOp, Field.Index);
// Fill the field descriptor with the existing field information...
Check(DbiGetFieldDescs(Tab
// Set the pointer to the index in the field descriptor to make the
// midifications to the field
Inc(pFields, Field.Index);
// If the szName portion of the ChangeRec has something in it, change it...
if StrLen(Rec.szName) > 0 then
pFields^.szName := Rec.szName;
// If the iType portion of the ChangeRec has something in it, change it...
if Rec.iType > 0 then
pFields^.iFldType := Rec.iType;
// If the iSubType portion of the ChangeRec has something in it, change it...
if Rec.iSubType > 0 then
pFields^.iSubType := Rec.iSubType;
// If the iLength portion of the ChangeRec has something in it, change it...
if Rec.iLength > 0 then
pFields^.iUnits1 := Rec.iLength;
// If the iPrecision portion of the ChangeRec has something in it, change it...
if Rec.iPrecision > 0 then
pFields^.iUnits2 := Rec.iPrecision;
Dec(pFields, Field.Index);
for B := 1 to Table.FieldCount do begin
pFields^.iFldNum := B;
Inc(pFields, 1);
end;
Dec(pFields, Table.FieldCount);
// Blank out the structure...
FillChar(TableDesc, sizeof(TableDesc), 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...
StrPCopy(TableDesc.szTblTy
// The following three lines are necessary when doing any field restructure
// operations on a table...
// Set the field count for the table
TableDesc.iFldCount := Table.FieldCount;
// Link the operation descriptor to the table descriptor...
TableDesc.pecrFldOp := pOp;
// Link the field descriptor to the table descriptor...
TableDesc.pFldDesc := pFields;
// Close the table so the restructure can complete...
Table.Close;
// Call DbiDoRestructure...
Check(DbiDoRestructure(hDb
finally
if pFields <> nil then
FreeMem(pFields);
if pOp <> nil then
FreeMem(pOp);
end;
end;
//autoInc->Integer
procedure TForm1.Button1Click(Sender
var CR : ChangeRec;
begin
Table1.Close;
Table1.Exclusive := True;
Table1.Open;
FillChar(CR,SizeOf(CR),0);
CR.iType := fldINT32;
ChangeField(Table1,Table1.
Table1.Close;
end;
//integer->autoinc, does not work, if table is not empty
procedure TForm1.Button2Click(Sender
var CR : ChangeRec;
begin
Table1.Close;
Table1.Exclusive := True;
Table1.Open;
FillChar(CR,SizeOf(CR),0);
CR.iType := fldPDXAUTOINC; //works only if table empty
ChangeField(Table1,Table1.
Table1.Close;
end;
end.
try it out
meikl ;-)
ASKER
Hi kretzsmar,
Thanks, I'll give it a try but I need
it to work both ways because I need
to create a new structure a table (extra fields and fields changes) but keep the same auto-inc values.
Database desktop does it but I need to
do it with code!
I'll give you 50 points if
auto-inc->integer works.
Any other ideas to solve my problem!
Thanks, I'll give it a try but I need
it to work both ways because I need
to create a new structure a table (extra fields and fields changes) but keep the same auto-inc values.
Database desktop does it but I need to
do it with code!
I'll give you 50 points if
auto-inc->integer works.
Any other ideas to solve my problem!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
hi kretszmar
Youre right! Integer->auto-inc does
not work in DB Desktop if not
empty table. I must have
done on a empty table and thought it will work in any cenario.
Thanks.
Youre right! Integer->auto-inc does
not work in DB Desktop if not
empty table. I must have
done on a empty table and thought it will work in any cenario.
Thanks.
hi skeleton,
(are you really so thin?)
thanks for accepting my comment as an answer. ;-)
sorry, about the impossibility of the vice versa implementation.
good luck again
meikl ;-)
(are you really so thin?)
thanks for accepting my comment as an answer. ;-)
sorry, about the impossibility of the vice versa implementation.
good luck again
meikl ;-)
ASKER
hi kretzsmar,
not at all - trying to loose weight ;-)
thanks
skeleton
not at all - trying to loose weight ;-)
thanks
skeleton
for what database?
meikl