強烈感謝PPower.
ADO多表更新的代碼,welcome指正xuchaofei@jit.com.tw,
//-------------------------------------------------------------------------------------------------------------------------------------------
在.h文件中 定義一個這樣的結構:
struct FieldValue
{
AnsiString FNName;
Variant FNValue;
} ;
struct FieldInfor
{
std::vector<FieldValue> MyValue;
};
//-----------
在private部分中定義下面函數:
std::vector<FieldInfor>MyFieldInfor;
std::vector<FieldValue>TableField;
void __fastcall GetTheUpdateTable(std::vector<AnsiString>&TableName);
void __fastcall BeforePostEv(TDataSet *DataSet);
//-----------------------
在cpp文件中:
在訂義了多表的SQL語句的DataSet的BeforePost事件中加入如下代碼:
BeforePostEv(DataSet);
//-----------------------
void __fastcall TMutableOp::BeforePostEv(TDataSet *DataSet)
{
if(DataSet->Modified)
{
FieldInfor TempVector;
for(int i=0; i<DataSet->FieldCount; ++i)
{
FieldValue AllField;
AllField.FNName = DataSet->Fields->Fields[i]->FieldName;
AllField.FNValue = DataSet->Fields->Fields[i]->Value;
TempVector.MyValue.push_back(AllField);//把有數據更改的那個字段的數據的全部內容全部都保存起來。
}
MyFieldInfor.push_back(TempVector);
}
}
//---------------------------------
//假設已取得了改變了的字段,那麼對它進行比較,看是那個表的數據,分表更新。
void __fastcall TMutableOp::GetTheUpdateTable(std::vector<AnsiString>&TableName)
{
std::auto_ptr<TADOQuery>Query(new TADOQuery(NULL));
Query->Connection = ADOConnection1;
//-------------------------------------------------------------
for(std::size_t i=0;i< MyFieldInfor.size();++i) // 1 for
{
for(std::size_t t=0;t<TableName.size(); ++t)//按表名來分類處理
{
AnsiString KeyFieldID;
AnsiString KeyFieldValue;
TableField.clear();
for(std::size_t j=0; j< MyFieldInfor[i].MyValue.size(); ++j ) //3 for
{
//這裡是一個視圖被更改的一條記錄
//對記錄按表分類:
AnsiString StrTemp = MyFieldInfor[i].MyValue[j].FNName;
if(StrTemp.Delete(TableName[t].Length()+1,StrTemp.Length()) ==TableName[t])//
{ //如果是這個表的字段,如果是Key字段,則把它記下,如果不是,則讓它組成SQL語句
AnsiString Temp;
Temp = MyFieldInfor[i].MyValue[j].FNName;
Temp.Delete(1,TableName[t].Length());
Temp.Delete(5,Temp.Length());//除表名後的前面四個字符,看看是不是"_Key"
if(Temp == "_Key")
{//是關建字段 ;把數據存到一個項量裡
//把字段的附加信息除去
AnsiString TempA = MyFieldInfor[i].MyValue[j].FNName;;
TempA.Delete(1,TableName[t].Length());//把表名去除
TempA.Delete(1,5); //把_Key去除,得到真實字段名
FieldValue FieldStruct;
KeyFieldID = TempA;
KeyFieldValue = MyFieldInfor[i].MyValue[j].FNValue;
FieldStruct.FNName =TempA;
FieldStruct.FNValue = MyFieldInfor[i].MyValue[j].FNValue;
TableField.push_back(FieldStruct);
}
else
{
FieldValue FieldStruct;
AnsiString TempA = MyFieldInfor[i].MyValue[j].FNName;;
TempA.Delete(1,TableName[t].Length());//把表名去除
TempA.Delete(1,2); //把__去除
FieldStruct.FNName = TempA;
FieldStruct.FNValue = MyFieldInfor[i].MyValue[j].FNValue;
TableField.push_back(FieldStruct);
}
}
else
{
//如果表名不一樣,什麼也不做
}
}// 3 for
//對第一個表的數據,到此找完,因些在這裡做更新SQL語句的合成
if(TableField.size()==0)
return;
AnsiString SQL;
SQL =" Select ";
for(std::size_t v=0 ;v <TableField.size()-1 ;++v)
{
SQL+= TableField[v].FNName + " , ";
}
SQL += TableField[TableField.size()-1].FNName+" ";// 到些應組成了類如這樣的字串"Select FA,FB,FC "
//加上表名 +條件
SQL += " From "+ TableName[t]+ " Where "+ KeyFieldID +" = " + KeyFieldValue;
Query->SQL->Text = SQL;
Query->Open();//取出了這個表中符合這個ID條件的記錄。然後進行比較,後付值
while(!Query->Eof) //這 個SQL語句選 出來的結果只能有一條記。
{
for(int F=0; F< Query->FieldCount; ++F)
{
if(Query->Fields->Fields[F]->Value == TableField[F].FNValue);
else
{
{
Query->Edit();
Query->Fields->Fields[F]->Value = TableField[F].FNValue;
Query->Post();//更新回數據庫;
}
}
}
Query->Next();
}
Query->Close();
}
}
}
//--------------------------------------------------------------------
更新表的按扭代碼為:
std::vector<AnsiString>tableName;
tableName.push_back("AA");//AA為表名:,把要更改表的名稱插入Vector
tableName.push_back("BB");//BB為表名
GetTheUpdateTable(tableName);
//---------------------------------------------
OK啦。
記錄DataSet要設成批更新模式。切記,切記。
有些不好的地方就是SQL語句的寫法不是很好。但沒辦法。因為我還沒有解決我上面問到的題。
還有有些地方不合理,如果做了很多次的POST,每改動一條記錄就Post了一次,如果一次改過超萬條的話,這樣做可是不行的。!!!!!!!!!!!!!!!!!!!!!1
有很多沒有必要的空循環。
我只能通過SQL語句來加下相應的辨別信息:
如:
Select A.ID as AA_Key_ID,A.Name as AA__Name ,A.StdNO as AA__StdNO ,B.Mark as BB__Mark , B.ID as BB_Key_ID from AA as A,BB as B where A.stdNO = B.stdNO
//----------AA,BB為表名:
每個表的關建字段要給出:我用 "表名 + _Key +關建字段名"來表示,
每個字段的的名字都要用:"表名+ __ + 字段名來分別"
上面的SQL語句,如果沒有加上附加信息:SQL就像這個樣子:
Select A.Id,A.Name,A.stdNO,B.Mark,B.ID from AA as A,BB as B
所以寫SQL語句有些繁,這只是多表修改的,刪除 ,和新增的代碼 在理解些代碼的基礎下可寫出。
實現的思原則是:把每一條改動過記錄記錄下來,然後拿這個記錄按表分類。再拿它來和數據庫原數據進行比較,如果不一樣,改之。