在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
曾经查过资料,后来忘了,现在做一下记录。 --------- 在 sql 语句里占位使用 一个冒号和一个用来表示这个位置的符号, 例如:SELECT * FROM aTableName WHERE aCol = :ColVal SELECT * FROM aTableName WHERE aCol = :ColVal 对占位了的地方赋值这里使用的是 paremeters 属性的 paramByName 作的, 例如: LDataSet.Parameters.ParamByName('ColVal').Value := 'SomeValue'; --------- 最近在 Delphi 7 中通过参数化的方式存汉字字符串,出现只存入了一部分的情况,搜索资料并测试之后,发现设置 DataType = ftWideString 可以解决。 示例: LCommand.Parameters.ParamByName('AKeyName').DataType := ftWideString; LCommand.Parameters.ParamByName('AKeyName').Value := '我没有,我不是,别瞎说'; DataType 的类型:DB.pas/TFieldType --date=2019-08-16
--------- 为了使贴出来的代码具有完成性和尽量的简单性, 把以前的代码改写了一下, 现在的代码是控制台程序, 在程序体中对数据库访问代码作了简单的调用. --------- 今天重新看了一遍代码,发现一个问题,就是 程序入口里的变量 QueryResult 所使用过的对象都没有释放!!! --date=2019-09-11 --------- 数据访问单元的代码: 1 unit uDBAccesser; 2 3 interface 4 5 uses 6 System.Generics.Collections, Data.Win.ADODB; 7 8 9 type TTAbleInfo = record 10 DataSource : String; 11 DbName : String; 12 Username : String; 13 Password : String; 14 Name : String; 15 IntCol : String; 16 TxtCol : String; 17 end; 18 19 type TEntity = record 20 SomeInt : Integer; 21 SomeTxt : String; 22 end; 23 24 type TDBAccesser = class 25 private 26 FConn : TADOConnection; 27 28 function Query( const ASql : String; const AParams : TDictionary<String, Variant>) : TList<TEntity>; 29 // 广泛含义的更新 30 function Update(Const ASql : String; const AParams : TDictionary<String, Variant>) : Boolean; overload; 31 public 32 constructor Create(); 33 destructor Destroy(); override; 34 35 function QueryAll() : TList<TEntity>; 36 function QueryByInt(const AInt : Integer) : TList<TEntity>; 37 function QueryByTxt(const ATxt : String ) : TList<TEntity>; 38 function InsertOne(const AEntity : TEntity) : Boolean; 39 function Delete(const AEntity : TEntity) : Boolean; 40 // 狭义的更新 41 function Update(const AOldValue : TEntity; const ANewValue : TEntity) : Boolean; overload; 42 end; 43 44 45 var 46 TableInfo : TTableInfo; 47 48 implementation 49 50 uses 51 System.SysUtils, System.Variants, Winapi.ActiveX; 52 53 54 constructor TDBAccesser.Create(); 55 const // MS SQL 56 LConnStrFormat : String = 'provider=SQLOLEDB.1;password=%s;User ID=%s;' 57 + 'Initial CataLog=%s;Data source=%s;'; 58 var 59 LConnStr : String; 60 begin 61 try 62 LConnStr := Format(LConnStrFormat, [TableInfo.Password, TableInfo.Username, 63 TableInfo.DbName, TableInfo.DataSource]); 64 65 Self.FConn := TADOConnection.Create(nil); 66 Self.FConn.ConnectionString := LConnStr; 67 Self.FConn.LoginPrompt := False; 68 Self.FConn.Connected := True; 69 except 70 on Err : Exception do begin 71 FreeAndNil(Self.FConn); 72 WriteLn('Error on create DBAccesser: ' + Err.Message); 73 end; 74 end; 75 end; 76 77 destructor TDBAccesser.Destroy; 78 begin 79 FreeAndNil(Self.FConn); 80 end; 81 82 83 function TDBAccesser.Query(const ASql: string; const AParams: TDictionary<System.string,System.Variant>) : TList<TEntity>; 84 var 85 LDataSet : TADODataSet; 86 LRow : TEntity; 87 LKey : String; 88 begin 89 LDataSet := nil; 90 try 91 LDataSet := TADODataSet.Create(nil); 92 LDataSet.Connection := Self.FConn; 93 LDataSet.CommandText := ASql; 94 95 // 我印象有篇文章说这句必须要有, 但不写也没发现问题 96 LDataSet.Parameters.ParseSQL(LDataSet.CommandText, True); 97 if (AParams <> nil) then begin 98 for LKey in AParams.Keys do begin 99 LDataSet.Parameters.ParamByName(LKey).Value := AParams.Items[LKey]; 100 end; 101 end; 102 103 LDataSet.Open; 104 LDataSet.First; 105 106 Result := TList<TEntity>.Create(); 107 while not LDataSet.Eof do begin 108 LRow.SomeInt := LDataSet.FieldByName(TableInfo.IntCol).AsInteger; // 也可以这种格式 LDataSet.Fields[0].AsBoolean; 109 LRow.SomeTxt := LDataSet.FieldByName(TableInfo.TxtCol).AsString; 110 111 Result.Add(LRow); 112 113 LDataSet.Next; 114 end; 115 finally 116 FreeAndNil(LDataSet); 117 end; 118 end; 119 120 function TDBAccesser.Update(Const ASql : String; const AParams : TDictionary<String, Variant>) : Boolean; 121 var 122 LCmd : TADOCommand; 123 LKey : String; 124 LRowsAffected : Integer; 125 begin 126 Result := False; 127 LCmd := nil; 128 try 129 LCmd := TADOCommand.Create(nil); 130 LCmd.Connection := Self.FConn; 131 LCmd.CommandText := ASql; 132 133 LCmd.Parameters.ParseSQL(LCmd.CommandText, True); 134 135 if (AParams <> nil) then begin 136 for LKey in AParams.Keys do begin 137 LCmd.Parameters.ParamByName(LKey).Value := AParams.Items[LKey]; 138 end; 139 end; 140 141 // 也可以直接在 EmptyParam 的位置直接写 [Param1, Param2, ...] 格式的内容, 142 // 而不使用上面的 Parameters,两者不能同时使用, 143 // 但具体什么情况我也忘了,相应代码也找不到了,要想知道真实情况,还得再动手去摸索 144 LCmd.Execute(LRowsAffected, EmptyParam); 145 146 if (LRowsAffected > 0) then begin 147 Result := True; 148 end 149 else begin 150 Result := False; 151 end; 152 finally 153 FreeAndNil(LCmd); 154 end; 155 end; 156 157 158 function TDBAccesser.QueryAll() : TList<TEntity>; 159 const 160 LSqlFormat : String = 'SELECT %s, %s FROM %s'; 161 var 162 LSql : String; 163 begin 164 LSql := Format(LSqlFormat, [TableInfo.TxtCol, TableInfo.IntCol, TableInfo.Name]); 165 166 Result := Self.Query(LSql, nil); 167 end; 168 169 function TDBAccesser.QueryByInt(const AInt: Integer) : TList<TEntity>; 170 const 171 LSqlFormat : String = 'SELECT %s, %s FROM %s WHERE %s = :$Int '; 172 var 173 LSql : String; 174 LParams : TDictionary<String, Variant>; 175 begin 176 LParams := TDictionary<String, Variant>.Create(); 177 try 178 LSql := Format(LSqlFormat, [TableInfo.TxtCol, TableInfo.IntCol, 179 TableInfo.Name, TableInfo.IntCol]); 180 181 LParams.Add('$Int', AInt); 182 183 Result := Self.Query(LSql, LParams); 184 finally 185 FreeAndNil(LParams); 186 end; 187 end; 188 189 function TDBAccesser.QueryByTxt(const ATxt: String) : TList<TEntity>; 190 const 191 LSqlFormat : String = 'SELECT %s, %s FROM %s WHERE %s = :$Txt '; 192 var 193 LSql : String; 194 LParams : TDictionary<String, Variant>; 195 begin 196 LParams := TDictionary<String, Variant>.Create(); 197 try 198 LSql := Format(LSqlFormat, [TableInfo.TxtCol, TableInfo.IntCol, 199 TableInfo.Name, TableInfo.TxtCol]); 200 201 LParams.Add('$Txt', ATxt); 202 203 Result := Self.Query(LSql, LParams); 204 finally 205 FreeAndNil(LParams); 206 end; 207 end; 208 209 function TDBAccesser.InsertOne(const AEntity: TEntity) : Boolean; 210 const 211 LSqlFormat : String = 'INSERT INTO %s (%s, %s) ' 212 + 'VALUES (:$Txt, :$Int) '; 213 var 214 LSql : String; 215 LParams : TDictionary<String, Variant>; 216 begin 217 LParams := TDictionary<String, Variant>.Create(); 218 try 219 LSql := Format(LSqlFormat, [TableInfo.Name, TableInfo.TxtCol, TableInfo.IntCol]); 220 221 LParams.Add('$Txt', AEntity.SomeTxt); 222 LParams.Add('$Int', AEntity.SomeInt); 223 224 Result := Self.Update(LSql, LParams); 225 finally 226 FreeAndNil(LParams); 227 end; 228 end; 229 230 function TDBAccesser.Delete(const AEntity: TEntity) : Boolean; 231 const 232 LSqlFormat : String = 'DELETE FROM %s ' 233 + 'WHERE %s = :$Txt AND %s = :$Int '; 234 var 235 LSql : String; 236 LParams : TDictionary<String, Variant>; 237 begin 238 LParams := TDictionary<String, Variant>.Create(); 239 try 240 LSql := Format(LSqlFormat, [TableInfo.Name, TableInfo.TxtCol, TableInfo.IntCol]); 241 242 LParams.Add('$Txt', AEntity.SomeTxt); 243 LParams.Add('$Int', AEntity.SomeInt); 244 245 Result := Self.Update(LSql, LParams); 246 finally 247 FreeAndNil(LParams); 248 end; 249 end; 250 251 function TDBAccesser.Update(const AOldValue: TEntity; const ANewValue: TEntity) : Boolean; 252 const 253 LSqlFormat : String = 'UPDATE %s ' 254 + 'SET %s = :$TxtVal, %s = :$IntVal ' 255 + 'WHERE %s = :$OldTxtVal AND %s = :$OldIntVal '; 256 var 257 LSql : String; 258 LParams : TDictionary<String, Variant>; 259 begin 260 LParams := TDictionary<String, Variant>.Create(); 261 try 262 LSql := Format(LSqlFormat, [TableInfo.Name, 263 TableInfo.TxtCol, TableInfo.IntCol, 264 TableInfo.TxtCol, TableInfo.IntCol]); 265 266 LParams.Add('$TxtVal', ANewValue.SomeTxt); 267 LParams.Add('$IntVal', ANewValue.SomeInt); 268 269 LParams.Add('$OldTxtVal', AOldValue.SomeTxt); 270 LParams.Add('$OldIntVal', AOldValue.SomeInt); 271 272 Result := Self.Update(LSql, LParams); 273 finally 274 FreeAndNil(LParams); 275 end; 276 end; 277 278 279 initialization 280 TableInfo.DataSource := '.'; 281 TableInfo.DbName := 'simpleTestByX'; 282 TableInfo.Username := 'sa'; 283 TableInfo.Password := '123456'; 284 TableInfo.Name := 'tab_simple_test'; 285 TableInfo.IntCol := 'some_int'; 286 TableInfo.TxtCol := 'some_txt'; 287 288 CoInitialize(nil); 289 290 finalization 291 CoUninitialize(); 292 293 294 end.
控制台程序入口代码,对上面的单元进行简单的调用: 1 program ProjectParameterizedSql; 2 3 {$APPTYPE CONSOLE} 4 5 {$R *.res} 6 7 uses 8 System.SysUtils, 9 System.Generics.Collections, 10 uDBAccesser in 'uDBAccesser.pas'; 11 12 13 function FormatEntity(AEntity : TEntity) : String; 14 begin 15 Result := Format(' SomeInt = %d, SomeTxt = %s ', [AEntity.SomeInt, AEntity.SomeTxt]); 16 end; 17 18 19 var 20 DBAccesser : TDBAccesser; 21 EntityQuery : TEntity; 22 EntityInsert : TEntity; 23 EntityDelete : TEntity; 24 EntityUpdateNew : TEntity; 25 EntityUpdateOld : TEntity; 26 EntityCommon : TEntity; 27 QueryResult : TList<TEntity>; 28 begin 29 try 30 DBAccesser := TDBAccesser.Create(); 31 try 32 WriteLn('1) insert one: '); 33 34 EntityInsert.SomeInt := 1; 35 EntityInsert.SomeTxt := 'Hello'; 36 WriteLn(' entity = ', FormatEntity(EntityInsert)); 37 38 WriteLn(' insert success? ', DBAccesser.InsertOne(EntityInsert)); 39 WriteLn('----------------'); 40 41 WriteLn('2) query all: '); 42 43 QueryResult := DBAccesser.QueryAll(); 44 45 WriteLn(' total = ', QueryResult.Count); 46 for EntityCommon in QueryResult do begin 47 WriteLn(' ', FormatEntity(EntityCommon)); 48 end; 49 WriteLn('----------------'); 50 51 WriteLn('3) update: '); 52 53 EntityUpdateOld := EntityInsert; 54 EntityUpdateNew.SomeInt := 2; 55 EntityUpdateNew.SomeTxt := 'World'; 56 57 WriteLn(' old : ', FormatEntity(EntityUpdateOld)); 58 WriteLn(' new : ', FormatEntity(EntityUpdateNew)); 59 60 WriteLn(' update success? ', DBAccesser.Update(EntityUpdateOld, EntityUpdateNew)); 61 WriteLn('----------------'); 62 63 WriteLn('4) query by int:'); 64 65 EntityQuery := EntityUpdateNew; 66 WriteLn(' int = ', EntityQuery.SomeInt); 67 68 QueryResult := DBAccesser.QueryByInt(EntityQuery.SomeInt); 69 70 WriteLn(' total : ', QueryResult.Count); 71 for EntityCommon in QueryResult do begin 72 WriteLn(' ', FormatEntity(EntityCommon)); 73 end; 74 WriteLn('----------------'); 75 76 WriteLn('5) query by txt:'); 77 78 EntityQuery := EntityUpdateNew; 79 WriteLn(' txt = ', EntityQuery.SomeTxt); 80 81 QueryResult := DBAccesser.QueryByTxt(EntityQuery.SomeTxt); 82 83 WriteLn(' total : ', QueryResult.Count); 84 for EntityCommon in QueryResult do begin 85 WriteLn(' ', FormatEntity(EntityCommon)); 86 end; 87 WriteLn('----------------'); 88 89 WriteLn('6) delete:'); 90 91 EntityDelete := EntityUpdateNew; 92 WriteLn(' entity = ', FormatEntity(EntityDelete)); 93 94 WriteLn(' delete success? ', DBAccesser.Delete(EntityDelete)); 95 WriteLn('----------------'); 96 97 WriteLn('7) query all: '); 98 99 QueryResult := DBAccesser.QueryAll(); 100 WriteLn(' total : ', QueryResult.Count); 101 for EntityCommon in QueryResult do begin 102 WriteLn(' ', FormatEntity(EntityCommon)); 103 end; 104 WriteLn('----------------'); 105 106 WriteLn(' 全部评论
专题导读
上一篇:Delphi中DLL初始化和退出处理发布时间:2022-07-18下一篇:Delphi2009泛型容器单元(Generics.Collections)[1]:TListT发布时间:2022-07-18热门推荐
热门话题
阅读排行榜
|
请发表评论