2013-03-22 64 views
1

很多时候,当我们查询数据库,我们只需要使用VARCHAR一列。 所以我做了一个很好的功能,查询数据库,并把结果放在一个StringList的:数据库变结构导致

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; 

我觉得这是值得的基础上。

回答

7

您应该使用任何断开内存TDataSet后裔,如TClientDataSet

不要试图通过存储来重新发明轮子一个记录集的一些新的“变体”结构。 A 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']); 

许多TDataSets有可能被用来作为依赖于供应商和LockType的内存(客户端)数据集的能力,例如TADODataSetLockType=ltBatchOptimistic可以从服务器获取结果集,然后保持断开连接。

+0

我认为这是我需要研究的内容。 – 2013-03-22 15:18:15

1

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

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

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

当然,你能想到的东西构建智能,可以是作为一个数据集,但灵活的:较为一般的东西搞定,性能越差(一般)。

+0

我们遇到了一些问题,主要是2:1:性能真的嵌套查询遭受因为它并不总是很清楚的是,你使用的功能使用的数据库,所以嵌套并不总是很清楚。 2:在开放数据集上工作时,很难预测数据在打开时是否相同,以及在何时完成数据。 – 2013-03-22 15:17:16

+0

一旦你打开数据集,它就是静态的。将这些东西复制到另一个结构或迭代它们没有区别。然而,如果性能是一个问题,即你必须经常搜索,你当然必须将数据复制到另一个结构中:我会推荐POCO类和字典或类似的。 – alzaimar 2013-03-22 15:47:37

3

与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; 
+0

那些变体数组非常重量级。如果可以的话,我宁愿简单地使用'Variant'数组,但如果它适合Excel数据交换...尽管我认为最好的可能是由@kobik建议的'TCustomDataSet'。 [+1] – TLama 2013-03-22 14:32:41

+0

@bummi我们使用了一些oleautomation,我认为这种方法非常适合它。 – 2013-03-22 15:19:16