Sql server TSQLQuery截断数据

Sql server TSQLQuery截断数据,sql-server,database,delphi,sql-server-2008-r2,communication,Sql Server,Database,Delphi,Sql Server 2008 R2,Communication,我在2012年问过这个问题: 我想让这个问题保持简单,因此,与其在另一个问题上附加更多细节,希望人们能再看一遍,这是一个新问题,只包含核心细节 问题摘要 TSQLConnection…MaxBobSize有两种设置。使用-1会丢失数据(错误),使用X MB会耗尽内存: TSQLConnection.Params.Values['MaxBlobSize']:='-1',使TSQLQuery查看数据库中每个var.(max)字段的数据长度,并分配与每个字段的数据长度匹配的缓冲区。每个缓冲区中的前1

我在2012年问过这个问题:

我想让这个问题保持简单,因此,与其在另一个问题上附加更多细节,希望人们能再看一遍,这是一个新问题,只包含核心细节


问题摘要

TSQLConnection…MaxBobSize有两种设置。使用
-1
会丢失数据(错误),使用
X MB
会耗尽内存:

  • TSQLConnection.Params.Values['MaxBlobSize']:='-1'
    ,使
    TSQLQuery
    查看数据库中每个
    var.(max)
    字段的数据长度,并分配与每个字段的数据长度匹配的缓冲区。每个缓冲区中的前1048576字节设置正确,然后剩余字节设置为NULL(
    0x00
    )。因此,数据丢失

  • TSQLConnection.Params.Values[MaxBlobSize]:=“X MB”
    makes
    TSQLQuery
    为查询中返回的每个
    var.(max)
    字段预分配指定的
    X MB
    内存
    X MB
    必须足够大,以容纳最大的
    var.(max)
    对象。即使在
    10MB
    ,一个包含3个
    var.(max)
    字段和100行的查询将预先分配
    3GB
    内存来为查询服务,即使实际数据要小得多。如果机器内存不足,用户会看到“灾难性故障”


  • 详细信息

    2012年,我们与Embarcadero合作解决了bug#1。他们所说的使用
    xmb
    而不是
    -1
    ,这会导致我们的用户体验到状况2。我们继续使用
    MaxBlobSize:=-1
    希望Embarcadero最终能够修复#1,或者我们的用户永远不会超过1MB限制

    一个用户向数据库上传了一个10MB的图像,这种情况很可能再次发生。当他们检索10MB图像时,前1MB图像显示正确,其余图像丢失。完整的10MB图像正确存储在数据库中。因此,用户遇到了错误1

    这个问题仍然存在于DelphiSeattle(XE10)中,正如这个简单的测试用例所演示的。我通过WireShark验证了来自db的流量包括所有字段数据

  • 创建一个新的Delphi VCL表单项目
  • SQLConnection1:TSQLConnection
    添加到表单中,设置以访问数据库:

    • 驱动程序=MSSQL
    • 主机名=本地主机
    • OSAuthentication=True
    • 数据库=tempdb
    • LoginPrompt=False
  • SQLConnection1.Params['MaxBlobSize']
    设置为
    -1

  • 使用以下
    OnClick()
    code添加
    按钮1:t按钮
  • procedure TForm1.按钮1点击(发送方:TObject);
    变量
    qry:TSQLQuery;
    过程保存(fn:字符串);
    变量
    数据:t字节;
    fs:TFileStream;
    开始
    fs:=TFileStream.Create('c:\'+fn+'.txt',fmCreate);
    尝试
    数据:=qry.FieldByName(fn).AsBytes;
    如果数据为零,则
    fs.WriteBuffer(数据[0],长度(数据));
    最后
    FreeAndNil(fs);
    结束;
    结束;
    开始
    SQLConnection1.Open;
    qry:=TSQLQuery.Create(nil);
    尝试
    qry.MaxBlobSize:=-1;
    qry.SQLConnection:=SQLConnection1;
    qry.SQL.Text:=Concat(
    '声明@s1 varchar(最大值),@s2 varchar(最大值)',
    'set@s1='0123456789ABCDEF',
    “set@s2=@s1+@s1+@s1+@s1+@s1+@s1+@s1/*128字节*/”,
    “set@s1=@s2+@s2+@s2+@s2+@s2+@s2+@s2+@s2/*1024字节*/”,
    'set@s2=@s1+@s1+@s1+@s1+@s1+@s1+@s1/*8192字节*/',
    “set@s1=@s2+@s2+@s2+@s2+@s2+@s2+@s2+@s2/*65536字节*/”,
    “set@s2=@s1+@s1+@s1+@s1+@s1+@s1+@s1/*524288字节*/”,
    'set@s1=@s2+@s2/*1048576字节*/',
    'set@s2=@s1+''这是一个测试'/*1MB+14字节*/',
    紧急广播系统“/*1MB+36字节*/”的“set@s1=@s1+”,
    '选择@s2作为Plus14,@s1作为Plus36'
    );
    qry.打开;
    保存(“Plus14”);
    保存(“Plus36”);
    最后
    FreeAndNil(qry);
    结束;
    SQLConnection1.Close;
    结束;
    
  • 运行应用程序并单击按钮
  • 在十六进制编辑器中打开每个文件,并在每个文件末尾查找空值(
    0x00

  • 问题

    由于用户在使用
    MaxBobSize:=X MB
    时遇到内存不足问题,我们需要保持
    MaxBobSize:=-1
    。是否有人有任何建议或解决方案可以将
    MaxBlobSize
    设置为
    -1
    ,继续使用
    TSQLConnection
    TSQLQuery
    ,然后访问所有字段数据,即使字段超过1MB


    如果无法使用上述组件,则使用本机组件的另一种解决方案也可以。

    FWIW我使用TADO。。。组件,并且从来没有任何数据大小问题。一直存储和检索图像…我同意@Peter的观点。我承认,我一点也不清楚为什么要将dbExpress与Sql Server结合使用——这会让你依赖EMBA来修复它们的bug,而且在任何情况下,Delphi附带的TAdo*组件都是围绕MS经过尝试和测试的ADO层的相对较薄的包装,后者的用户基础要大得多,因此bug要少得多。如果使用TAdo*组件fwiw在Delphi中开发,我自己20年来从未遇到过ADO错误。这两个都是非常好的评论。我修改了问题中的测试用例以使用ADO组件,您是对的,它们在没有提到问题的情况下工作。是时候切换到ADO了。我之所以使用dbExpress组件,是因为我们使用了DataSnap,并且已经将dbExpress与DataSnap一起使用了。吸取的教训。。。