首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TClientDataSet和大插入

TClientDataSet和大插入
EN

Stack Overflow用户
提问于 2009-11-06 12:25:04
回答 4查看 2K关注 0票数 3

在我的应用程序中,我将TADOQuery与select (MSSQL)结合使用,并将其链接到TClientDataSet。我必须插入大约百万张唱片和ApplyUpdates。

那么,我在Server事件探查器中看到了什么?我看到对于每个插入的行,我们有3个查询:插入脚本的sp_prepare、带有一些值的sp_execute以及sp_unprepare。

我只想一次为插入前的所有记录准备一次,然后取消它的准备。我该怎么做呢?

在之后添加

在查询中,我有一个用于存储过程执行的脚本:

代码语言:javascript
复制
tmpQuery := DefineQuery(FConnection, [
  'exec up_getOperatorDataSet ',
  '  @tablename     = :tablename, ',
  '  @operator      = :operator, ',
  '  @forappend     = :forappend, ',
  '  @withlinksonly = :withlinksonly, ',
  '  @ids           = :ids '
], [
  Param(ftString, sTableName),
  Param(ftInteger, FOperatorId),
  Param(ftBoolean, opForAppendOnly in OpenParams),
  Param(ftBoolean, opOnlyWithModelLinks in OpenParams),
  Param(ftString, sIds)
], Result);

它使用一些参数从表sTableName中选择所有字段。

从分析器插入的示例:

步骤1:

代码语言:javascript
复制
declare @p1 int
set @p1=486
exec sp_prepare @p1 output,N'@P1 int,@P2 int,@P3 datetime,@P4 int,@P5 int,@P6 int,@P7 int,@P8 int,@P9 varchar(128),@P10 bit,@P11 numeric(19,4),@P12 smallint,@P13 smallint,@P14 smallint,@P15 smallint',N'insert into parser_prices
  (operator_id, request_id, date, nights, model_hotel_id, model_meal_id, model_room_id, model_htplace_id, spo, hotelstop, price, frout_econom, frout_business, frback_econom, frback_business)
values
  (@P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9, @P10, @P11, @P12, @P13, @P14, @P15)
',1
select @p1

步骤2:

代码语言:javascript
复制
exec sp_execute 486,21,2000450,'2009-12-04 00:00:00',14,2118,22,-9555,18,'2009-10.MSK.Bali.13.10.09-27.03.10',0,15530.0000,3,3,3,3

步骤3:

代码语言:javascript
复制
exec sp_unprepare 486

它是用于新行的所有的。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-11-12 13:42:48

答案是在TADOConnection中使用的提供者中。从MSDASQL切换到SQLOLEDB,现在就可以了,没有任何额外的查询。

票数 0
EN

Stack Overflow用户

发布于 2009-11-07 11:46:47

因为您调用的是存储过程,而不是代码中的内联查询,所以SQL Server将对存储过程的每个调用视为单独的调用,因此每次都要准备和取消它。我不确定是否有办法解决这个问题。

如果存储的proc中发生的任何事情都可以通过代码中的查询来完成,那么您可以使用这样的结构,它只在第一次准备SQL语句:

代码语言:javascript
复制
{Prepare the insert query}
ADOQuery1.SQL.Append('INSERT INTO Tablename');
ADOQuery1.SQL.Append('(StringField1, IntField2)');             {repeat as necessary}
ADOQuery1.SQL.Append('VALUES (:sFieldValue1, :sFieldValue2)'); {repeat as necessary}
ADOQuery1.SQL.Prepare;

{In a For, While, Repeat loop, use:}
ADOQuery1.ParamByName('sFieldValue1').AsString := 'Value for field 1';
ADOQuery1.ParamByName('sFieldValue2').AsInteger := 2;
ADOQuery1.ExecSQL;

很抱歉,如果我没有为ADOQuery组件获得正确的属性和方法名称,我目前不在Delphi上,而且我通常不使用TADO组件,但是这个概念仍然适用,因为这是一个TDataSet概念。

票数 1
EN

Stack Overflow用户

发布于 2009-11-11 20:24:00

思想..。

  1. 您不需要准备存储过程调用。实际上,它已经准备好了。您可以在大多数客户端实现中取消它。
  2. 您可能无法在一次执行中完成一百万行。您有一个批处理大小限制(如单个DB调用) 256 MB (假设默认的4k网络数据包)。
  3. 在其他客户端实现中,您可以设置一个"批次尺寸“(与第2点不同的概念),例如10,000个,因此您只需拨打100个电话,而不是100万个。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1687253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档