【问题标题】:Variable structure for database results数据库结果的可变结构
【发布时间】:2013-03-22 14:05:04
【问题描述】:

很多时候,当我们查询数据库时,我们只需要一列带有 varchar。 所以我做了一个很好的函数来查询数据库并将结果放在一个字符串列表中:

function Getdatatostringlist(sqlcomponent, sqlquery: string): TStringlist;

我现在正在寻找的基本上是相同的功能,但对于具有多列的结果,您事先不知道数据是什么类型,无论是 varchar、int、datetime。

在这里使用什么样的数据结构比较好。

我想要这个的原因是我尽量不处理开放数据集。我更喜欢将所有结果提取到一个临时结构中,关闭数据集并处理结果。


在 Kobiks 回复关于在内存数据集中使用的问题后,我想出了以下内容,很快就将其放在一起来测试这个概念:

procedure TForm1.Button2Click(Sender: TObject);
var
  MyDataSet : TAdoDataSet;
begin
 MyDataSet := GetDataToDataSet('SELECT naam FROM user WHERE userid = 1', ADOConnection1);
 try
   Form1.Caption := MyDataSet.FieldByName('naam').AsString;
 finally
   MyDataSet.free;
 end;
end;

function TForm1.GetDataToDataSet(sSql: string; AdoConnection: TADOConnection): TAdoDataSet;
begin
  Result := TAdoDataSet.Create(nil);
  Result.LockType := ltBatchOptimistic;
  Result.Connection := AdoConnection;
  Result.CommandText :=  sSql;
  Result.Open;
  Result.Connection := nil;
end;

我认为这是可以建立的。

【问题讨论】:

    标签: sql delphi


    【解决方案1】:

    您应该使用任何断开连接的内存中TDataSet 后代,例如TClientDataSet

    不要试图通过将记录集存储在一些新的“变体”结构中来重新发明轮子。 TClientDataSet 已经包含操作“临时”数据结构所需的所有功能。

    以下是创建TClientDataSet 结构的方法:

    cds.FieldDefs.Add('id', ftInteger);
    cds.FieldDefs.Add('name', ftString, 100);
    // ...
    // create it
    cds.CreateDataSet; 
    // add some data records
    cds.AppendRecord([1, 'Foo']);
    cds.AppendRecord([2, 'Bar']);
    

    许多 TDataSet 可以用作内存(客户端)数据集,具体取决于提供者和 LockType,例如带有 LockType=ltBatchOptimisticTADODataSet 可以从服务器获取结果集,然后保持断开连接。

    【讨论】:

    • 我认为这是我需要研究的。
    【解决方案2】:

    对于与 Excel 交换数据,此结构很有用,可能对其他用途有用。

    Function GetDatasetasDynArray(Ads: TDataset; WithHeader: Boolean = true): Variant;
    // 20130118 by Thomas Wassermann
    var
      i, x, y: Integer;
      Fields: Array of Integer;
    begin
      x := 0;
      y := Ads.RecordCount;
      if WithHeader then
        inc(y);
      SetLength(Fields, Ads.FieldCount);
      for i := 0 to Ads.FieldCount - 1 do
        if Ads.Fields[i].Visible then
        begin
          Fields[x] := i;
          inc(x);
        end;
      SetLength(Fields, x);
      Result := VarArrayCreate([0, y - 1 , 0, length(Fields) - 1], VarVariant);
      y := 0;
      if WithHeader then
      begin
        for i := Low(Fields) to High(Fields) do
        begin
          Result[y, i] := Ads.Fields[Fields[i]].DisplayLabel;
        end;
        inc(y);
      end;
      try
        Ads.DisableControls;
        Ads.First;
        while not Ads.EOF do
        begin
          for i := Low(Fields) to High(Fields) do
          begin
            Result[y, i] := Ads.Fields[Fields[i]].Value;
          end;
          Ads.Next;
          inc(y);
        end;
      finally
        Ads.EnableControls;
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
     DynArray:Variant;
    begin
    
       DynArray := GetDatasetasDynArray(Adodataset1,true);
       //DynArray[0,x] Header or First row
       //DynArray[1,x] First row or SecondRow
       Excel.Range.Value := DynArray;
    end;
    

    【讨论】:

    • 那些变体数组非常重量级。如果可以的话,我宁愿简单地使用array of Variant,但如果它有利于Excel 数据交换......虽然我认为最好的可能是@kobik 建议的TCustomDataSet。 [+1]
    • @bummi 我们使用了一些 oleautomation,我认为这种方法非常适合它。
    【解决方案3】:

    您为什么不喜欢使用开放数据集?他们通常不会阻止服务器。将数据从数据集中复制到任何你想要的地方是额外的开销,这很可能是不必要的。

    数据集提供了您想要的功能:具有可变列和行的矩阵。

    编辑:但是,如果您经常遍历数据集,您应该考虑创建一个保存相关信息的类,然后将数据复制到通用列表、字典、树或任何您需要的快速查找结构中。

    当然,您可以考虑构建智能的东西,它可以像数据集一样灵活,但是:越通用的东西,性能越差(通常)。

    【讨论】:

    • 我们遇到了一些问题,主要是 2 个: 1:性能确实受到嵌套查询的影响,因为您使用的函数使用数据库并不总是很清楚,所以嵌套并不总是很清楚. 2:在处理开放数据集时,很难预测数据是否与打开时的数据相同,而当您完成一半时。
    • 打开数据集后,它是静态的。将内容复制到另一个结构或迭代它没有区别。但是,如果性能是一个问题,即您必须经常搜索内容,那么您当然必须将数据复制到另一个结构中:我会推荐 POCO 类和字典或类似的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2021-07-01
    • 2015-03-20
    相关资源
    最近更新 更多