You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi10.4 ClientDataSet调用SQL Server存储过程参数异常空格问题求助

Delphi 10.4 Android调用SQL Server存储过程参数乱码/空格问题解决

问题场景

使用Delphi 10.4开发Android程序,通过TSQLConnection(DataSnap)搭配TClientDataSet调用SQL Server存储过程时,参数传递后尾部出现大量异常空格/乱码,执行update table1 set ddate = @date时触发“从字符串转换日期和/或时间时失败”错误。

原Delphi代码

var orderNo,date:string;

orderNo := '';
date := '2024-02-04 00:00:00';

With QSysDataSet do
begin
    close; 
    commandText:= 'exec S_SignSR :orderNo,:Date';

    Params.ParamByName('orderNo').dataType := ftstring;
    Params.ParamByName('orderNo').ParamType := ptInputOutput;
    Params.ParamByName('orderNo').size := 20;
    Params.ParamByName('orderNo').value := orderNo;

    Params.ParamByName('Date').dataType := ftstring;
    Params.ParamByName('Date').ParamType := ptInputOutput;
    Params.ParamByName('Date').size := 30;
    Params.ParamByName('Date').value := date;

    execute;
end.

对应SQL Server存储过程

create procedure S_SignSR
    @orderNo varchar(20) output,
    @date varchar(30) output
as
begin
    update table1 set ddate = @date 
end

已尝试无效方案

  • 显式设置参数Size时,参数长度额外增加1,尾部填充空格
  • 跳过设置Size,参数仍存在多余空格
  • 使用AsString赋值出现乱码,甚至参数值被截断
  • 转换字符串编码(WideString/AnsiString/UTF8Encode)均无效
  • 仅在存储过程中用substring(@date,1,19)截取可临时规避,但未解决参数传递本身问题

可行解决方案

方案1:匹配正确的参数数据类型

不要用ftString处理日期参数,改用SQL Server对应的日期类型;字符串参数匹配存储过程的varchar类型,使用ftVarChar而非ftString(ftString对应SQL的char,会自动补空格)。

修改后代码:

With QSysDataSet do
begin
    close; 
    commandText:= 'exec S_SignSR :orderNo,:Date';

    // 处理orderNo:对应varchar(20)输出参数
    Params.ParamByName('orderNo').dataType := ftVarChar;
    Params.ParamByName('orderNo').ParamType := ptInputOutput;
    Params.ParamByName('orderNo').size := 20;
    Params.ParamByName('orderNo').value := orderNo;

    // 处理Date:直接用日期类型而非字符串
    Params.ParamByName('Date').dataType := ftDateTime;
    Params.ParamByName('Date').ParamType := ptInput; // 存储过程中未修改@date,无需Output
    Params.ParamByName('Date').value := StrToDateTime(date);

    execute;
end;

同时修改存储过程的参数类型(如果ddate是datetime类型):

create procedure S_SignSR
    @orderNo varchar(20) output,
    @date datetime -- 改为datetime类型,移除output
as
begin
    update table1 set ddate = @date 
end

方案2:使用标准存储过程调用方式

不要用exec拼接命令,而是设置CommandType为ctStoredProc,让组件自动处理参数映射,避免手动拼接导致的编码问题。

修改后代码:

With QSysDataSet do
begin
    close; 
    CommandType := ctStoredProc;
    CommandText := 'S_SignSR'; // 直接指定存储过程名

    // 重置参数并配置
    Params.Clear;
    // 添加orderNo参数
    Params.CreateParam(ftVarChar, 'orderNo', ptInputOutput).Size := 20;
    Params.ParamByName('orderNo').Value := orderNo;
    // 添加date参数
    Params.CreateParam(ftDateTime, 'date', ptInput).Value := StrToDateTime(date);

    Execute;
end;

方案3:调整DataSnap连接的字符集

在TSQLConnection的连接参数中,设置CharacterSet为与SQL Server数据库匹配的值(如UTF-8或SQL_Latin1_General_CP1_CI_AS),避免编码转换时产生乱码。

可在连接字符串中添加:

CharacterSet=UTF8;

或在设计时,直接在TSQLConnection的Params属性中设置CharacterSet对应值。

方案4:修正存储过程参数的Output属性

存储过程中@date参数被设为output,但实际未对其赋值修改,属于冗余设置。改为input参数后,组件无需预留输出缓冲区,可避免额外的空格/乱码。

修改后的存储过程:

create procedure S_SignSR
    @orderNo varchar(20) output,
    @date varchar(30) -- 移除output属性
as
begin
    update table1 set ddate = @date 
end

内容的提问来源于stack exchange,提问作者sky find

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:11:30