ado数据编辑问题(50分)

  • 主题发起人 主题发起人 ZBJ2001_KF
  • 开始时间 开始时间
Z

ZBJ2001_KF

Unregistered / Unconfirmed
GUEST, unregistred user!
在数据表中字段如下<br>商品ID,数量,单价.<br><br>在录入窗体以DBGridEh显示 商品ID,商品名称,数量,单价.由于原表没有商品名称这个字段<br>我在AdoDataSet.CommandText := 'select a.*,space(50) as 商品名称 from a'<br>我主要是想在dbgrideh中显示出品名就可以了.不需要用加lookup字段. 可结果是根据就不能录入商品名称这个字段.
 
直接在ADO中是不能改的,因为构造的字段,在取得的表结构元数据中就被置为只读。想达到你要的效果。可以将程序改为<br>ADODataSet + DataSetprovider 取得数据包,然后在ClientDateSet中复制表的结构,并去掉只读属性,再将原数据复制回到Clientdataset中,此时就可以修改了。<br>给你几个实用的函数<br>//传递连接,可以得到所需的数据包<br>Function GetClientData(Conn:TADOConnection; SqlTxt:String; StructOnly:Boolean = False):OleVariant;<br>var tpQuery: TADOQuery;<br>&nbsp; &nbsp; tpProvider: TDataSetProvider;<br>&nbsp; &nbsp; CDS : TClientDataSet;<br>begin<br>&nbsp; Result := Null;<br>&nbsp; tpQuery:= TADOQuery.Create(nil);<br>&nbsp; tpProvider:= TDataSetProvider.Create(nil);<br>&nbsp; try<br>&nbsp; &nbsp; SetADOConn(tpQuery, Conn);<br>&nbsp; &nbsp; tpProvider.DataSet := tpQuery;<br>&nbsp; &nbsp; tpQuery.SQL.Text := SqlTxt;<br>&nbsp; &nbsp; tpQuery.Open;<br>&nbsp; &nbsp; if StructOnly then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; CDS := TClientDataSet.Create(Nil);<br>&nbsp; &nbsp; &nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CDS.Data := tpProvider.Data;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; While CDS.RecordCount &gt; 0 do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CDS.Delete;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := CDS.Data;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CDS.Close<br>&nbsp; &nbsp; &nbsp; &nbsp; Finally<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CDS.Free;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; if tpQuery.RecordCount &gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := tpProvider.Data;<br>&nbsp; &nbsp; tpQuery.Close;<br>&nbsp; Finally<br>&nbsp; &nbsp; tpQuery.Free;<br>&nbsp; &nbsp; tpProvider.Free;<br>&nbsp; End;<br>end;<br><br>//复制异构的数据集中的记录<br>Function CopyRecord(DataPkg:OleVariant; CDS:TClientDataSet):Boolean;<br>var tpCDS:TClientDataSet;<br>&nbsp; i:Integer;<br>&nbsp; tpStr:String;<br>begin<br>&nbsp; Result:=False;<br>&nbsp; if VarIsNull(DataPkg) then<br>&nbsp; &nbsp; Exit;<br>&nbsp; tpCDS:=TClientDataSet.Create(nil);<br>&nbsp; try<br>&nbsp; &nbsp; tpCDS.Data:=DataPkg;<br>&nbsp; &nbsp; with tpCDS do begin<br>&nbsp; &nbsp; &nbsp; if (RecordCount=0) or (FieldCount=0) then<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; &nbsp; &nbsp; CDS.FieldDefs := FieldDefs;<br>&nbsp; &nbsp; &nbsp; For i := 0 to CDS.FieldDefs.Count &nbsp;- 1 do<br>&nbsp; &nbsp; &nbsp; &nbsp; CDS.FieldDefs.Items.Attributes := CDS.FieldDefs.Items.Attributes -[faReadonly];<br>&nbsp; &nbsp; &nbsp; CDS.CreateDataSet;<br>&nbsp; &nbsp; &nbsp; First;<br>&nbsp; &nbsp; &nbsp; While Not Eof do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; CDS.Append;<br>&nbsp; &nbsp; &nbsp; &nbsp; for i:=0 to FieldCount-1 do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tpStr:=Trim(Fields.FieldName);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if Assigned(CDS.FindField(tpStr)) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CDS.FieldByName(tpStr).Value:=Fields.Value;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; CDS.Post;<br>&nbsp; &nbsp; &nbsp; &nbsp; Next;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; if CDS.State in [dsEdit,dsInsert] then<br>&nbsp; &nbsp; &nbsp; &nbsp; CDS.Post;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; Result:=True;<br>&nbsp; Finally<br>&nbsp; &nbsp; tpCDS.Close;<br>&nbsp; &nbsp; FreeAndNil(tpCDS)<br>&nbsp; End;<br>end;<br><br>使用方法<br>var tpData: OleVariant;<br><br>tpData := GetClientData(ADOConn, 'select a.*,space(50) as 商品名称 from a');<br><br>CopyRecord(tpData, ClientDataSet1);<br>将DataSource 与 ClientDataset1连接后,在表格中即能显示和编辑数据。
 
要么就别用dbgrideh。用stringgrid一样可以显示数据库信息,可以随便 加列,用前者简单,要实现你说的功能挺复杂的。
 
由于是在群里的讨论,有朋友说不方便在这贴出就。就删除了。
 
查资料说是改ADO的动态属性可以控件更新指定的表。<br>adoQuery1.Properties['unique table'].value := 'tablea';<br>可发现只控制执行DELETE ,只删除指定的表中行。<br>但在更新和新增上控制不了。
 
你在走弯路,大哥<br>应该是SQL Server的数据库,<br>它是支持 left join select语句的更新的。<br>select a.*,b.商品名称 from a left join b on a.商品ID=b.商品ID<br>就可以了 <br>然后你设置 b.商品名称那一列只读 就好了<br>或者用 dbgrideh的 lookuplist 你不要 不用这个 不用那个的 ,怎么简单效率高才是最重要的
 
to wyb_506 你说的有道理。原来我是用LEFT JOIN。更新自己写SQL语句。<br><br>现我想有ADODataSet来实现更新。那只能用LOOKUP了。主要是想把一件事搞清楚些
 
既然 你只需要 显示的话,那么数据来源是什么,ado本身是支持你说的功能的另外还有betterado封装了这个特性,另外还有zeoslib 的tupdatesql有支持关联表的更新某一个表的功能,delphi本身的确没有给出标准答案,需要自己找.<br>支持你的精神不错的哈学习ing.
 
好 学习的话 这样<br>我的印象里 ClientDateSet 只是一个数据集的复制品,存在于本地内存中。更新的时候,根据它与dataProvider里面指向的数据集进行一对一的对应 就好像两个ID相等那样,进行两个数据集比较和更新,这就是为什么能够实现undo redo功能的原因 至于ADOQuery实现的undo redo功能 则是模拟了这一过程。<br>如果dateprovider 里面没有列A &nbsp;则更新的时候 是不可能更新到的 哈哈 估计说明白了吧
 
我知道不能更新,但我想实现这样的效果,没有好的办法.
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
D
回复
0
查看
767
DelphiTeacher的专栏
D
后退
顶部