to yzqyb: 客户端有简单认证,如果实际应用,肯定需要自己根据项目情况增加一些认证措施。 to carcode: 你说的这个真不算问题,如果有需要你可以在服务端给其他客户端发个修改了那个表的通知。 to newapple :1.日期(字符串存储)查询要用19位长度的字符串如:2009-01-01 12:00:00 2.因为Filter属性被我的代码使用了:) to dcopyboy:下一版本将自动查找ID字段,就不要求非要在第1个了。我还是不建议指定ID字段的字段名,那样使用起来会不太方便,还是做成自动的好些 :)。
to All: 谢谢大家支持,希望喜欢它的朋友一起来把这个东东越做越好,让更多的人能得到它提供的方便和高效。
笔者认为,不如我们指定自增长字段名更为合理,下列修改就是针对本想法的: 修改untRmoDbClient单元的下列2个过程: procedure TRmoClient.OnBeforeDelete(DataSet: TDataSet); var I: Integer; lsql: string; Result, ltablename: string; // Lkey, lvalue: string; Lindex: integer; begin //获取表名 lsql := LowerCase(TADOQuery(DataSet).Filter); if Pos('select', lsql) > 0 then begin if lglst = nil then lglst := TStringList.Create; GetEveryWord(lsql, lglst, ' '); for i := 0 to lglst.Count - 1 do if lglst.Strings[i] = 'from' then begin Lindex := i; Break; end; if Lindex < 2 then ExceptTip('SQL语句错误!'); ltablename := ''; for i := Lindex + 1 to lglst.Count - 1 do if lglst.Strings[i] <> '' then begin ltablename := lglst.Strings[i]; Break; end; if ltablename = '' then ExceptTip('SQL语句错误!'); end else ExceptTip('无法自动提交,请先执行select'); //获取方法 with DataSet.Fields do begin if DataSet.FindField(IndexField) <> nil then Result := 'delete from ' + ltablename + Format(' where ' + IndexField + '=%d', [FieldbyName(IndexField).AsInteger]) else Result := 'delete from ' + ltablename + Format(' where %s=%d', [Fields[0].FieldName, Fields[0].AsInteger]); ExeSQl(Result); end; end;
procedure TRmoClient.OnBeginPost(DataSet: TDataSet); var I: Integer; lsql: string; Result, ltablename: string; Lkey, lvalue: string; Lindex: integer; IDFileName: string; begin //获取表名 lsql := LowerCase(TADOQuery(DataSet).Filter); if Pos('select', lsql) > 0 then begin if lglst = nil then lglst := TStringList.Create; GetEveryWord(lsql, lglst, ' '); for i := 0 to lglst.Count - 1 do if lglst.Strings[i] = 'from' then begin Lindex := i; Break; end; if Lindex < 2 then ExceptTip('SQL语句错误!'); ltablename := ''; for i := Lindex + 1 to lglst.Count - 1 do if lglst.Strings[i] <> '' then begin ltablename := lglst.Strings[i]; Break; end; if ltablename = '' then ExceptTip('SQL语句错误!'); end else ExceptTip('无法自动提交,请先执行select'); //获取方法
case TADOQuery(DataSet).State of // dsinsert: begin IDFileName := ''; with DataSet.Fields do begin //如果第一个字段为只读,说明是自增长ID字段 改掉它 if DataSet.FindField(IndexField) <> nil then begin IsInserIDfield := True; FieldbyName(IndexField).ReadOnly := False; IDFileName := IndexField; end else if Fields[0].ReadOnly = true then begin IsInserIDfield := True; Fields[0].ReadOnly := False; IDFileName := Fields[0].FieldName; end; Result := 'insert into ' + ltablename + '('; for i := 0 to count - 1 do if (IDFileName <> '') and (IDFileName <> Fields[i].FieldName) then Result := Result + Fields[i].FieldName + ','; Result := copy(Result, 1, length(Result) - 1); Result := Result + ') values ('; for i := 0 to Count - 1 do if (IDFileName <> '') and (IDFileName <> Fields[i].FieldName) then begin case Fields[i].DataType of ftCurrency, ftBCD, ftWord, ftFloat, ftBytes: Result := Result + Fields[i].AsString + ','; ftSmallint, ftInteger: Result := Result + IntToStr(Fields[i].AsInteger) + ','; else Result := Result + '''' + Fields[i].AsString + '''' + ','; end; end; Result := copy(Result, 1, length(Result) - 1) + ')'; ExeSQl(Result); if IsInserIDfield then begin //如果需要ID字段 自动获取 if FQryForID = nil then FQryForID := TADOQuery.Create(nil); if DataSet.FindField(IndexField) <> nil then begin OpenAndataSet(Format('select max(%s) as myid from %s', [IndexField, ltablename]), FQryForID); Fieldbyname(IndexField).AsInteger := FQryForID.FieldByName('myid').AsInteger; end else begin OpenAndataSet(Format('select max(%s) as myid from %s', [Fields[0].FieldName, ltablename]), FQryForID); Fields[0].AsInteger := FQryForID.FieldByName('myid').AsInteger; end; end; end; end; dsEdit: begin with DataSet.Fields do begin Result := 'Update ' + ltablename + ' Set '; if DataSet.FindField(IndexField) <> nil then begin IDFileName := IndexField; Lkey := Fieldbyname(IndexField).FieldName; lvalue := Fieldbyname(IndexField).AsString; end else begin IDFileName := Fields[0].FieldName; Lkey := Fields[0].FieldName; lvalue := Fields[0].AsString; end; for I := 0 to count - 1 do // Iterate if (IDFileName <> '') and (IDFileName <> Fields[i].FieldName) then begin Result := Result + Fields[i].FieldName + '='; case Fields[i].DataType of // ftCurrency, ftBCD, ftWord: Result := Result + Fields[i].AsString; ftFloat: Result := Result + Fields[i].AsString; ftBytes, ftSmallint, ftInteger: Result := Result + IntToStr(Fields[i].AsInteger); else Result := Result + '''' + Fields[i].AsString + ''''; end; // case Result := Result + ','; end; // for Result := copy(Result, 1, length(Result) - 1) + Format(' where %s=%s', [Lkey, lvalue]); end; // with ExeSQl(Result); end; end; // case end; 其中的IndexField为指定自增长字段名,可定义在UntBaseProctol单元中!
To swgweb : 呵呵 谢谢你的热心,我回头创建一个SVN。 to thinknet:关于SQl注入的问题,应该由应用层根据项目情况在上层应用来做处理,因为如果在底层对各字段内容做处理的话,会降低使用效率。而且也不是每个项目都必须。 To All 感谢大家的支持,因为INDY有版本兼容的问题,我已经将客户端修改为Dxsock版本,这样不管那个版本的DELPHI都能编译(D2009除外),近期写个Demo后,连同支持大二进制字段一起上传到盒子。