在Delphi中使用复杂的SQL (经验分享)(0分)

  • 主题发起人 主题发起人 flexitime
  • 开始时间 开始时间
F

flexitime

Unregistered / Unconfirmed
GUEST, unregistred user!
在Delphi中要用使用数据库,要使用SQL语句,我想每个稍为用Delphi写过程序的人都会知道怎么用,举个ADO的例子来说 <br><br>var <br>&nbsp;qry : TADOQuery; <br>begin <br>&nbsp; qry := TAdoQuery.Create(nil); <br>&nbsp; qry.Connection := cnn; <br>&nbsp; qry.SQL.add('select * from ta where id = :id'); <br>&nbsp; qry.Parameters.ParamByName('id').Value := 123; <br>&nbsp; qry.open; <br>.... <br>如果查询语句比较简单的,那么用上面的方法确实也没有什么问题,但如果SQL语句是比较复杂的,可能就会这个样子了: <br><br>sqlcore := 'select age, icdm10, ta.* &nbsp;from BAGL_BA2 , ( ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'select jzh, riqi, fph, jine, sbje, &nbsp;nvl(sbje, 0) - nvl(other_sum, 0) as sbsfje, jsfs ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'from fp1 where fpbz &nbsp;&lt;&gt; ''2'' ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'and riqi &gt;= to_date(:bd1, ''yyyymmdd'') ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'and riqi &nbsp;&lt; to_date(:ed1, ''yyyymmdd'') ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'union all select jzh, riqi, yddh, -ydje,sbje, 0 as sbsfje, jsfs from tf ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'where riqi &gt;= to_date(:bd2, ''yyyymmdd'') ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'and riqi &nbsp;&lt; to_date(:ed2, ''yyyymmdd'') ' + <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ') ta where bagl_ba2.jzh(+) = ta.jzh '; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>qry.SQL.Add(sqlcore); &nbsp;<br>或者直接用qry.SQL.Add逐句增加也行,但工作量不会减轻多少(几乎没有区别)。 <br>在这里要注意空格以外,还要注意原来要用引号的地方,特别的麻烦,而且SQL的原排版格式也全废掉了。如果语句日后要作修改的话,那就更加麻烦了。 <br>曾经有几位用PowerBuilder的朋友对我说,他们对Delphi这种方式相当讨厌,因为在PB里面可以内嵌SQL脚本,写SQL语句时相当的舒服,他们老是劝我用PB。但我对使用PB完全没有兴趣,而且我用Delphi也不止是为了写数据库的软件。 <br>最近,我发现一个比较好的解决方法,如某个Form中要用一句比较复杂的SQL语句(不要说要用View,有些时候View不能解决问题的,SP也是一样的道理),那么在这个Form上面加上一个memo控件,把它的visible设为false,另在memo.lines属性中把要写的SQL语句原样贴进去,接着在程序中就这样写 <br><br>var <br>&nbsp;qry : TADOQuery; <br>begin <br>&nbsp; qry := TAdoQuery.Create(nil); <br>&nbsp; qry.Connection := cnn; <br>&nbsp; qry.SQL.add(memo1.Text); <br>&nbsp; qry.Parameters.ParamByName('id').Value := 123; <br>&nbsp; qry.open; <br>.... <br>这样处理之后,要修改SQL的话就直接在memo中改就行了,而且SQL的原排版格式也得以保留,引号的问题也不用特别处理,相当的方便。 虽然有点浪费的问题,但我觉得这点内存的消耗对比消耗时间来整理SQL语句要划算得多。
 
直接在query的SQL中寫入不是更方便<br>最多多放几個Query而已
 
对于特复杂的sql, 用memo确实是个好办法<br>我一般定义SQL字符串变量<br>SQL:='select ... where xxx=%s';<br>SQL:=format(SQL, [quote()]);<br>tadodataset.commandtext:=sql; <br>我一般这样用
 
多放几个query控件,再用SQL语句实现是很方便的。我做的系统都是这样实现的
 
是啊,原来多放几个Query应该也是可以的,不过我做系统时有点特殊,我不用直接的可实例化的类,原因是我用的是CoreLib的DAC控件组,同时为了程序的通用性,我不指定用MyQuery或MSQuery或OraQuery,而只用它们共同的基类TCustomDADataSet,这个东西不能实例它的,所以也就无法象普通Query一样可用了。
 
不知道flexitime的memo中怎样表达,字段的内容等于窗体中的文本框的内容?
 
用存储过程吧
 
我也喜欢用存储过程,效率高,直接放在SQL2000服务器端。缺点是:无法保密源程序,很容易解密
 
存储过程可以加密 的
 
是你们对语句太不熟了,俺没感觉
 
所有sql语句可以放在exe之外,写个小程序来管理(为生成sql方便可以加些小功能),保存到文件,在exe运行时载入,写个函数根据名称或ID之类的来取相应的sql,像where条件之类的可以写成要这个条件就加了,不要就最后的sql里不有这个条件
 
存储过程是可以加密(WITH ENCRYPTION 子句),但是解密非常简单
 
to :aagen,<br>我的原则是尽量不拼接语句,因为这样十分容易出错,也不好维护。因此尽量利用Parameters等功能
 
楼主使用tmemo会占用比较多的系统资源,下面是我写的一个控件方便大家解决类似的问题<br>unit uVStringList;<br><br>interface<br>&nbsp; &nbsp; Uses &nbsp;Classes;<br><br>Type<br>&nbsp; TVMStringList=Class(TComponent)<br>&nbsp; private<br>&nbsp; &nbsp; FItems: TStrings;<br>&nbsp; &nbsp; FSorted: Boolean;<br>&nbsp; &nbsp; FOnChanging: TNotifyEvent;<br>&nbsp; &nbsp; FOnChange: TNotifyEvent;<br>&nbsp; &nbsp; procedure SetItems(const Value: TStrings);<br>&nbsp; &nbsp; function GetItems: TStrings;<br>&nbsp; &nbsp; procedure SetSorted(const Value: Boolean);<br>&nbsp; published<br>&nbsp; &nbsp; property Items:TStrings read GetItems write SetItems;<br>&nbsp; &nbsp; property Sorted: Boolean read FSorted write SetSorted;<br>&nbsp; &nbsp; property OnChange: TNotifyEvent read FOnChange write FOnChange;<br>&nbsp; &nbsp; property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(AOwner:TComponent);reintroduce;overload;<br>&nbsp; &nbsp; constructor Create;reintroduce;overload;<br>&nbsp; &nbsp; destructor Destroy;override;<br>&nbsp; &nbsp; procedure Sort; virtual;<br>&nbsp; end;<br>&nbsp; procedure Register;<br><br>implementation<br><br>{ TVMStringList }<br><br><br>procedure Register;<br>begin<br>&nbsp; RegisterComponents('bwCommon', [TVMStringList]);<br>end;<br><br>constructor TVMStringList.Create(AOwner: TComponent);<br>begin<br>&nbsp; &nbsp; inherited Create(AOwner);<br>&nbsp; &nbsp; FItems:=TStringList.Create;<br>&nbsp; &nbsp; with FItems as TStringList do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; OnChange:=FOnChange;<br>&nbsp; &nbsp; &nbsp; &nbsp; OnChanging:=FOnChanging;<br>&nbsp; &nbsp; end;<br>end;<br><br>constructor TVMStringList.Create;<br>begin<br>&nbsp; &nbsp; FItems:=TStringList.Create;<br>&nbsp; &nbsp; with FItems as TStringList do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; OnChange:=FOnChange;<br>&nbsp; &nbsp; &nbsp; &nbsp; OnChanging:=FOnChanging;<br>&nbsp; &nbsp; end;<br>end;<br><br><br><br>destructor TVMStringList.Destroy;<br>begin<br>&nbsp; FItems.free;<br>&nbsp; inherited;<br>end;<br><br><br><br>function TVMStringList.GetItems: TStrings;<br>begin<br>&nbsp; &nbsp; if Not Assigned(Fitems) then<br>&nbsp; &nbsp; &nbsp; &nbsp; FItems:=TStringList.Create;<br>&nbsp; &nbsp; result:=FItems;<br>end;<br><br>procedure TVMStringList.SetItems(const Value: TStrings);<br>begin<br>&nbsp; &nbsp; FItems.Assign(Value);<br>end;<br><br>procedure TVMStringList.SetSorted(const Value: Boolean);<br>begin<br>&nbsp; if FSorted &lt;&gt; Value then<br>&nbsp; begin<br>&nbsp; &nbsp; if Value then Sort;<br>&nbsp; &nbsp; FSorted := Value;<br>&nbsp; end;<br>end;<br><br>procedure TVMStringList.Sort;<br>begin<br>&nbsp; &nbsp; (FItems as TStringList).Sort;<br>end;<br><br>end.
 
后退
顶部