有办法动态改变数据库的字符型字段的长度吗?(100分)

  • 主题发起人 主题发起人 lop
  • 开始时间 开始时间
L

lop

Unregistered / Unconfirmed
GUEST, unregistred user!
有一个数据库(Paradox)中的一个字符型字段(A类型),需要在程序中动态
地改变它的宽度,用什么办法呢.
 
把它定义成Blob字段。
 
建议你用其他数据库,Varchar 型
 
//changed from bde sample
//This example uses the following input:
//
// ChangeField(Table1, Table1.FieldByName('FOO'), MyChangeRec)

//ChangeRec is defined as follows:

type

ChangeRec = packed record
szName: DBINAME;
iType: Word;
iSubType: Word;
iLength: Word;
iPrecision: Byte;
end;


//The function is defined as follows:

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 not Table.Active then
raise EDatabaseError.Create('Table must be opened to restructure');
if not Table.Exclusive then
raise EDatabaseError.Create('Table must be opened exclusively' +
'to restructure');
Check(DbiSetProp(hDBIObj(Table.Handle), curxltMODE, Integer(xltNONE)));
// Get the table properties to determine table type...
Check(DbiGetCursorProps(Table.Handle, Props));
// Make sure the table is either Paradox or dBASE...
if (Props.szTableType <> szPARADOX) and (Props.szTableType <> szDBASE) then
raise EDatabaseError.Create('Field 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(Table.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 (Length(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(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));

// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblName, Table.TableName);
// Put the table type in the table descriptor...
StrPCopy(TableDesc.szTblType, 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;

 
很感谢cytomn的回答,但因本人不懂英文和对DB API函数不熟悉,所以看了很久也看不懂cytomn给的程序,所以也不会用.想cytomn或其他高手给一个Change Field函数的使用实例,特别是ChangeRec如何赋值.
如现在有一个MyTable表,其中有一个字符字段为StrField,宽为10个字符,现想将其宽改为20个字符,ChangeRec应如何赋值.
 
var MyChangeRec:ChangeRec;
begin
Fillchar(MyChangeRec, sizeof(MyChangeRec), 0);
MyChangeRec.iLength:=20;
ChangeField(MyTable, MyTable.FieldByName('strfield1'), MyChangeRec);
end;
 
to tocywn:
按照你提供的函数和使用方法,编译时出现了很多未定义的数据类型,
:DBINAME,CURProps,hDBIDb....等.是不是要在uses中加一个什么
单元或要作其他的数据类型的定义,望再作指教,麻烦你了,谢谢!
 
cytown:
会不会是你给的使用方法有错呢,程序到调用DbiDoRestructure函数时就出错,
提示是'Invalid field name Table:D:/....',是ChangeRec结构中其他的变量
也要赋值吗?帮我想想办法吧,谢谢你了.
 
知道ChangeRec怎样赋值了:
ChangeRec.szName:='strField';
ChangeRec.iType:=0;
ChangeRec.iSubType:=0;
ChangeRec.iLength:=12;
ChangeRec.iPrecision:=0;
这样就没有问题了,可以改变字段的宽度。
谢谢cytown!
 
呵呵, 我的代码少了MyChangeRec.szName:='strField1';这句, 所以字段名要
变成'', 当然违法了:-)
 
多人接受答案了。
 
后退
顶部