【问题标题】:best way to insert data using dephi in sql server 2008在 sql server 2008 中使用 delphi 插入数据的最佳方法
【发布时间】:2013-09-16 07:40:34
【问题描述】:

我一直使用这样的脚本将数据插入到 delphi 7 中的表中

sql := 'INSERT INTO table_foo (field1,field2,field3) VALUES ('
+quotedstr('value1')
+','+quotedstr('value2')
+','+quotedstr('value3')
+')';
adoquery1.close;
adoquery1.sql.text := sql;
adoquery1.execsql;

但是我的一个朋友刚刚向我展示了另一种看起来更干净的方式,就像这样:

sql := 'SELECT * FROM table_foo';
adoquery1.close;
adoquery1.sql.text := sql;
adoquery1.open;
adoquery1.insert;
adoquery1.fieldbyname('field1').asstring := quotedstr('value1');
adoquery1.fieldbyname('field2').asstring := quotedstr('value2');
adoquery1.fieldbyname('field3').asstring := quotedstr('value3');
adoquery1.post;

这两种方法中哪一种更好(更快、更容易阅读/调试)?特别是当table_foo 中的数据很大或需要填写的字段较多时。

【问题讨论】:

  • 我什至不知道第二种语法;-)
  • 您应该阅读有关 cursors 的一般信息,特别是有关 可更新 游标的信息。后者是允许您的朋友使用该技巧的东西。当然,基本语句不会受到客户端游标分配开销的负担。

标签: sql sql-server delphi


【解决方案1】:

如果您确实使用INSERT INTO 语句,请使用参数(出于可读性的原因,请避免 SQL 注入、SQL 缓存),例如:

adoquery1.sql.text := 'INSERT INTO table_foo (field1, field2) values (:field1, :field2)';
adoquery1.Parameters.ParamByName('field1').Value := value1;
adoquery1.Parameters.ParamByName('field2').Value := value2; 

更喜欢第二种方式(我会稍作调整)。 由于您要插入一条记录,因此调整是选择一个 empty 记录集,即:

SELECT * FROM table_foo where 1=0

这样您就不会从表格中选择所有条记录。 分配值时也无需使用QuotedStr,即:

adoquery1.FieldByName('field1').AsString := 'value1';

我使用这种方法的主要原因是因为它易于阅读和维护。 我不需要用纯 SQL 查询来打扰自己。我不需要处理有时需要为参数指定数据类型的参数(例如Parameters.ParamByName('field1').DataType := ftInteger)。无需ParseSQL。 我只是使用 DataSet As(Type) 例如

FieldByName('field1').AsBoolean := True;

如果我需要在单个事务中插入多条记录,我也更喜欢使用这种方法。 第二种方法的缺点是通过SELECT FROM 访问 SQL 服务器的时间较短。

另一种选择是创建一个 SQL 存储过程,将值传递给 SP,然后在 SP 中编写所有 SQL 逻辑。

【讨论】:

  • 即使使用WHERE 1=0,第二个选项仍然会产生额外的数据库往返以获得架构信息的开销。因此,您可能需要采取一些措施来减少开销。 IE。尽可能重复使用数据集实例进行多次插入。 (Close 数据集可能没问题,只要您不更改 SQL 查询,它就会记住架构。但是,我不确定 - 所以您必须仔细检查。)
  • +1 for Parameters :) 人们更喜欢 INSERT 语法的一个重要原因是当您想要更快地执行 BULK INSERTS 时。
  • 请注意,在查询上调用PrepareCursor 也可以显着提高执行速度。
【解决方案2】:

第二种方法需要数据集中更多的本地资源,因为它将保留原始结果集的内存,然后使用该内存来决定应使用哪个 SQL 语句将哪些记录发送到服务器。该方法还需要与服务器的实时连接和数据集中的双向本地游标集。 TADODataset 为您做这一切。它对你的工作量更大,工作量更少,但它会从系统中消耗更多。在我看来,决定取决于哪个资源更重要,你的时间或计算机资源。

就个人而言,我更喜欢使用TClientDataset (CDS)。它将允许您拥有一个内存数据集,并通过在相应的TDatasetProvider 中使用TDatasetProvider.BeforeUpdateRecord 事件,您将获得两全其美:绝对控制将哪个句子提交给服务器以及灵活的双向数据集在 GUI 上效果很好。

此外(这对我来说是最重要的),使用 CDS,您将能够将 DBMS 的细节与应用程序的主要逻辑隔离开来,因为该逻辑将在独立于 DB 的数据集上运行。如果您必须从 ADO 转移到 DBX,您的主代码不会受到影响,因为它是在 CDS 上编写的。

【讨论】:

  • +1 表示“需要与服务器建立实时连接并在数据集中设置双向本地游标”。假设默认 ADO 设置,我在回答中从未提及。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 2019-05-28
  • 2012-08-06
相关资源
最近更新 更多