简单的问题,如何把delta数据转换成SQL语句?(50分)

  • 主题发起人 主题发起人 vickeen
  • 开始时间 开始时间
V

vickeen

Unregistered / Unconfirmed
GUEST, unregistred user!
请写成函数,贴出代码。
多谢了先!
 
一点也不简单。
你先告诉我delta具体数据结构我就告诉你代码
 
我做不到,所以关注。
 
delta包含的内容足够你产生sql了,但是你不要指望别人给你写好。
delta包含原始数据和修改纪录。修改即增加、删除、修改。这样delta的数据的每一纪录
有4个状态中一个状态:原始数据、增加、删除、修改。
delta给Tclientdataset,然后显示出来观察,发现有个字段表示状态(好像是state),这是
数据打包时自动增加的。
还有一点:每一个修改了的纪录后下一条纪录肯定是原始数据,用来定位用的。
数据的状态时整数型的。
但要产生sql还要根据updatemode和field的provideflag。
你这样的处理是经常遇到的。

 
var dataset:Tclientdataset;
...
begin
...
dataset.data:=data;//data是delta
with DataSetdo
begin
First;
while notEofdo
begin
if UpdateStatus = usInserted then
begin
Edit;
FieldByName('DateCreated').AsDateTime := Date;
Post;
end;
Next;
end;
UpdateStatus 就是那个标志。
 
文不对题,随便的想法:procedure TForm1.ClientDataSet1AfterApplyUpdates(Sender: TObject;
var OwnerData: OleVariant);
begin
ownerdata:='select * from a';
end;

procedure TForm1.DataSetProvider1BeforeApplyUpdates(Sender: TObject;
var OwnerData: OleVariant);
var
sqlstring:string;
begin
sqlstring:=vartostr(ownerdata);
end;
 
可以的,我曾經寫過,
但面對復雜的業務邏輯,作用不大的.
實際就是把clientdataset轉換成sql語句的.;思路如下
procedure TMrp.dspProdprocBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet;
DeltaDS: TClientDataSet;
UpdateKind: TUpdateKind;
var Applied: Boolean);
...
if uppercase(SourceDs.name)=uppercase('adoQprodproc') then
case updateKind of
ukModify:begin
create_D_update_sql(adoq,deltads,table名,[要操作的字段]);
end;

end;
....
procedure Create_D_update_sql(var sql: Tadoquery;
cds: Tclientdataset;
tabname: string;
strFld: array of string);
var
flds:integer;
tmpsql:string;
begin
if not ChkRecordExist(cds,tabname,strfld) then
//因為是ukModify 檢查記錄是否重復
begin
// setlasterror(ModifyError);
raise exception.Create('Record was chaged by another,Modify failure!');
end;
sql.close;
sql.sql.clear;
tmpsql:=' update '+tabname+' set ';
for flds:=0 to high(strFld)do
begin
tmpsql:=tmpsql+strfld[flds]+'=:'+trim(strfld[flds]+'1');
if flds<>high(strFld) then
tmpsql:=tmpsql+',';
end;
tmpsql:=tmpsql+' where ';
for flds:=0 to high(strFld)do
begin
if not (varisempty(cds.fieldbyname(strfld[flds]).oldvalue) or (cds.fieldbyname(strfld[flds]).oldvalue=null)) then
begin
tmpsql:=tmpsql+strfld[flds]+'=:'+trim(strfld[flds]+'2');
tmpsql:=tmpsql+' AND ';
end;
end;
tmpsql:=tmpsql+'1=1';
sql.SQL.add(tmpsql);
for flds:=0 to high(strFld)do
begin
if varisempty(cds.fieldbyname(strfld[flds]).newvalue) or (cds.fieldbyname(strfld[flds]).newvalue=null) then
sql.Parameters.ParamByName(TRIM(strfld[flds])+'1').value:=cds.fieldbyname(strfld[flds]).oldvalue
else
sql.Parameters.ParamByName(TRIM(strfld[flds])+'1').value:=cds.fieldbyname(strfld[flds]).newvalue;
if not (varisempty(cds.fieldbyname(strfld[flds]).oldvalue) or (cds.fieldbyname(strfld[flds]).oldvalue=null)) then
sql.Parameters.ParamByName(TRIM(strfld[flds])+'2').value:=cds.fieldbyname(strfld[flds]).oldvalue;
end;
 
可以自己解析,通过将Delta包赋值给TClientDataSet,TClientDataSet.Data := Delta
之后的处理便和处理一般的TClientDataSet的数据集一样了。
只是每条记录都会存在一个修改状态值UpdateStatus。根据状态值确定记录属性。
修改的记录会存在两条记录,第一条是修改后的记录,但只有更改的字段
第二条为修改后的记录,要通过这条记录写where语句
删除和增加的记录只有一条记录,只是UpdateStatus不一样。
通过自己解析可以完全生成一个SQL语句进行数据更新。
对于三层结构中的视图的更新这种用法比较不错。以前使用这种方法进行数据视图的提交
建议你可以去读一下Provider.pas。更直接的方法便是重写TProvider
 
多人接受答案了。
 
后退
顶部