ADO多表更新BCB實現


強烈感謝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語句有些繁,這只是多表修改的,刪除 ,和新增的代碼 在理解些代碼的基礎下可寫出。
實現的思原則是:把每一條改動過記錄記錄下來,然後拿這個記錄按表分類。再拿它來和數據庫原數據進行比較,如果不一樣,改之。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值