2016-03-29 6 views
1

私はDelphi 10 Seattleを使用しています。以下はサンプルコードです。TFDQueryを使用してSQLite内の2つのデータセットを結合した後に数値フィールドがTWideStringFieldになる理由

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient, 
    FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, 
    FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, 
    FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef, 
    FireDAC.Stan.ExprFuncs, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, 
    FireDAC.DApt, FireDAC.VCLUI.Wait, FireDAC.Comp.UI, FireDAC.Comp.Client, 
    FireDAC.Phys.SQLiteVDataSet, FireDAC.Comp.DataSet, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    ClientDataSet1: TClientDataSet; 
    ClientDataSet2: TClientDataSet; 
    FDConnection1: TFDConnection; 
    FDQuery1: TFDQuery; 
    FDLocalSQL1: TFDLocalSQL; 
    FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink; 
    FDGUIxWaitCursor1: TFDGUIxWaitCursor; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    public 
    procedure AfterConstruction; override; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.AfterConstruction; 
var o: TFDLocalSQLDataSet; 
begin 
    inherited; 
    ClientDataSet1.FieldDefs.Add('Code', ftString, 20); 
    ClientDataSet1.FieldDefs.Add('Amount', ftFMTBcd, 2); 
    ClientDataSet1.FieldDefs.Find('Amount').Precision := 18; 
    ClientDataSet1.CreateDataSet; 
    ClientDataSet1.AppendRecord(['A', 10]); 
    ClientDataSet1.AppendRecord(['B', 20]); 
    ClientDataSet1.AppendRecord(['C', 30]); 

    ClientDataSet2.FieldDefs.Add('Code', ftString, 20); 
    ClientDataSet2.FieldDefs.Add('Amount', ftFMTBcd, 2); 
    ClientDataSet2.FieldDefs.Find('Amount').Precision := 18; 
    ClientDataSet2.CreateDataSet; 
    ClientDataSet2.AppendRecord(['X', 10]); 
    ClientDataSet2.AppendRecord(['B', 20]); 
    ClientDataSet2.AppendRecord(['Y', 30]); 

    o := FDLocalSQL1.DataSets.Add; 
    o.DataSet := ClientDataSet1; 
    o := FDLocalSQL1.DataSets.Add; 
    o.DataSet := ClientDataSet2; 
    FDLocalSQL1.Active := True; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    if FDQuery1.Active then 
    FDQuery1.Close; 

    FDQuery1.Open(
    'SELECT * FROM ClientDataSet1 ' + 
    'UNION ' + 
    'SELECT * FROM ClientDataSet2' 
); 
    ShowMessage(FDQuery1.FindField('Amount').ClassName); 
end; 

end. 

TClientDataSetのインスタンスはどちらも同じフィールド構造(コードは文字列フィールド、金額はFMTBcdフィールド)です。

なぜFDQuery1.FindField( 'Amount')がTWideStringFieldを返しますか?

答えて

1

あなたのqはAmountフィールドが最初に数値であったことを前提としていますが、Sqliteが実際にどのように動作するかはわかりません。

Sqliteの列は厳密に型付けされていません.FireDACは、他の型の列を宣言しても、すべてのSqliteの列が本当に何であるか、つまりWideStringを教えています。 Sqliteでは、特定の型(f.i.自動インクリメント整数)になる列を定義することは、その列のデータが格納される方法よりもどのように動作するのかという問題です。

Fwiw、FireDACは一般に、DBExpressよりもSqliteカラムとメタデータの方が優れているようですが、依頼しているような "funnies"があります。

SqlLiteがFireDACに列タイプ名を指定すると、FireDACはその列に最初に現れる値の実際のデータ型を使用しようとします。 Nullの場合、FireDACは列の型としてftWideStringを使用します。

+0

ほとんど正解ですが、1つ追加してください。 SQLiteがUNIONのように列タイプ名をFireDACに提供する場合、FireDACは列の最初の値の実際のデータ型を使用しようとします。 NULLの場合、FireDACは列をftWideStringとして定義します。 –

関連する問題