Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi/FireDAC StrsTrim2Len对ParamByName没有影响_Delphi_Firebird2.5_Firedac - Fatal编程技术网

Delphi/FireDAC StrsTrim2Len对ParamByName没有影响

Delphi/FireDAC StrsTrim2Len对ParamByName没有影响,delphi,firebird2.5,firedac,Delphi,Firebird2.5,Firedac,在Firebird 2.5中使用Delphi XE7和Tokyo,我得出的结论是,StrsTrim2Len在使用TFDQuery和ParamByName进行更新/插入时没有任何影响,这使得过大的字符串引发异常 除了截断代码中的所有字符串,还有其他方法吗 ParamByName('Field1').AsString := SomeVar.SubString(0, 50); 还需要跟踪场地长度吗 其来源和形式如下: unit Unit3; interface uses Winapi.Wi

在Firebird 2.5中使用Delphi XE7和Tokyo,我得出的结论是,
StrsTrim2Len
在使用
TFDQuery
ParamByName
进行更新/插入时没有任何影响,这使得过大的字符串引发异常

除了截断代码中的所有字符串,还有其他方法吗

ParamByName('Field1').AsString := SomeVar.SubString(0, 50);
还需要跟踪场地长度吗


其来源和形式如下:

unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  System.StrUtils,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 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.FB,
  FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
  Vcl.StdCtrls, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FireDAC.Comp.UI, FireDAC.Phys.IBBase;

type
  TForm3 = class(TForm)
    FDConnection1: TFDConnection;
    FDPhysFBDriverLink1: TFDPhysFBDriverLink;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    FDQuery1: TFDQuery;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
begin
  FDConnection1.Open;

  FDQuery1.FormatOptions.StrsTrim2Len := True;

  FDQuery1.SQL.Text := 'INSERT INTO MyTable (ID, MyField) VALUES (:ID, :MyField)';
  FDQuery1.ParamByName('ID').AsInteger := 1;
  FDQuery1.ParamByName('MyField').AsString := DupeString('0', 21); { ← field is 20 chars }
  FDQuery1.ExecSQL;

  FDQuery1.SQL.Text := 'SELECT MyField FROM MyTable WHERE ID = 1';
  FDQuery1.Open;

  Assert(Length(FDQuery1.FieldByName('MyField').AsString) = 20); { ← trimmed to 20 chars? }

  FDConnection1.Close;
end;

end.
相应的.dfm文件:

object Form3: TForm3
  Left = 0
  Top = 0
  Caption = 'Form3'
  ClientHeight = 294
  ClientWidth = 161
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 40
    Top = 16
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object FDConnection1: TFDConnection
    Params.Strings = (
      'Database=MyUTF8Db'
      'User_Name=Sysdba'
      'Password='
      'Server=127.0.0.1'
      'CharacterSet=UTF8'
      'DriverID=FB')
    FormatOptions.AssignedValues = [fvStrsTrim2Len]
    FormatOptions.StrsTrim2Len = True
    Left = 48
    Top = 48
  end
  object FDPhysFBDriverLink1: TFDPhysFBDriverLink
    Left = 48
    Top = 104
  end
  object FDGUIxWaitCursor1: TFDGUIxWaitCursor
    Provider = 'Forms'
    ScreenCursor = gcrHourGlass
    Left = 48
    Top = 160
  end
  object FDQuery1: TFDQuery
    Connection = FDConnection1
    Left = 48
    Top = 216
  end
end
是否需要在启用STRSTRTRIM2LEN的情况下手动调整参数值? 否,启用该选项时,即使指定的参数值也应修剪到绑定字段的限制。因此,对于字符串字段参数IMHO,直接字符串赋值应在长度上修剪值

ParamByName('MyFieldUTF8').AsWideString := 'Value to be encoded by FireDAC';
为什么是伊姆霍?因为在这种特殊情况下(Delphi Tokyo,Firebird中的UTF-8字段),此选项的实现类似于
DataTrim2Size,而不是它的读取方式,我不确定是否有什么原因导致它落后。Firebird中的字符串字段在定义时受字符串长度限制而不是存储数据大小限制的约束(据我所知)

那么自动调整字符串参数值有什么问题? FireDAC现在用于Firebird驱动程序,仅当编码参数值的数据大小超过参数字段的存储数据大小时(当选项启用时),才会修剪UTF-8字段的参数数据缓冲区。所以它是基于数据大小而不是字符串长度

参数数据大小(如果未指定)似乎是从RDB$FIELDS系统表的RDB$FIELD_LENGTH元字段中获得的(无法确认,但从快速Firebird代码浏览中,成员似乎由该字段值填充)。但现在还没那么重要

问题在于这个代码和选项实际应该做什么的类比(这是TIBVariable.SetData方法实现,UTF-8分支;我添加的注释):

正如您可能猜到的,参数值缓冲区的修剪实际上会发生,但编码字符串的大小太小,因此修剪被跳过。您还可以预测,如果使用此类参数(例如,用于插入值),则最终会出现引擎异常,因为在验证约束时,引擎使用的是插入的字符串值长度,而不是数据大小

我在这里找不到使用数据大小的实际意义。当然,您永远不会溢出存储数据大小,但另一方面,您很容易超过字段的长度。讨论的选项是长度,而不是大小

我将打开一个bug报告,并尝试等待关于这个主题的一些评论,因为我不相信这段代码是一个意外。将返回报告..

是否需要在启用STRSTRTRIM2LEN的情况下手动修剪参数值? 否,启用该选项时,即使指定的参数值也应修剪到绑定字段的限制。因此,对于字符串字段参数IMHO,直接字符串赋值应在长度上修剪值

ParamByName('MyFieldUTF8').AsWideString := 'Value to be encoded by FireDAC';
为什么是伊姆霍?因为在这种特殊情况下(Delphi Tokyo,Firebird中的UTF-8字段),此选项的实现类似于
DataTrim2Size
,而不是它的读取方式,我不确定是否有什么原因导致它落后。Firebird中的字符串字段在定义时受字符串长度限制而不是存储数据大小限制的约束(据我所知)

那么自动调整字符串参数值有什么问题? FireDAC现在用于Firebird驱动程序,仅当编码参数值的数据大小超过参数字段的存储数据大小时(当选项启用时),才会修剪UTF-8字段的参数数据缓冲区。所以它是基于数据大小而不是字符串长度

参数数据大小(如果未指定)似乎是从RDB$FIELDS系统表的RDB$FIELD_LENGTH元字段中获得的(无法确认,但从快速Firebird代码浏览中,成员似乎由该字段值填充)。但现在还没那么重要

问题在于这个代码和选项实际应该做什么的类比(这是TIBVariable.SetData方法实现,UTF-8分支;我添加的注释):

正如您可能猜到的,参数值缓冲区的修剪实际上会发生,但编码字符串的大小太小,因此修剪被跳过。您还可以预测,如果使用此类参数(例如,用于插入值),则最终会出现引擎异常,因为在验证约束时,引擎使用的是插入的字符串值长度,而不是数据大小

我在这里找不到使用数据大小的实际意义。当然,您永远不会溢出存储数据大小,但另一方面,您很容易超过字段的长度。讨论的选项是长度,而不是大小


我将打开一个bug报告,并尝试等待关于这个主题的一些评论,因为我不相信这段代码是一个意外。是否将报告返回..

您是否尝试仅使用
复制
函数来复制字符串的一部分@亚伯:这就是子串的作用。无论如何,这两种方法都需要我跟踪参数引用的每个字段的长度,所以我想知道是否有其他方法可以避免这种情况。啊哈,您的数据库使用UTF-8编码。这就是我们的不同之处。快速查看,我可以说参数的数据大小错误。我会更深入地报告那个尺寸是从哪里来的。。如果大小正确,就会进行修剪。您是否尝试仅使用
复制
函数来复制字符串的一部分@亚伯:这就是子串的作用。无论如何,这两种方法都是可行的