繁体   English   中英

TADOStoredProc和SQL Server存储过程,参数为默认值

[英]TADOStoredProc and SQL Server stored procedure with parameter as default value

我正在使用Delphi 7和SQL Server2008。我已经创建了一个虚拟表和虚拟存储过程,如下所示。

CREATE TABLE [dbo].[Persons]
(
    [P_ID] [int] IDENTITY(1,1) NOT NULL,
    [LastName] [varchar](255) NOT NULL
)

CREATE PROCEDURE [dbo].[p_dummy_proc]
    @p_id int,
    @p_name VARCHAR(10) = 'dummy' -- donot pass anything from delphi and it should take 'dummy'
AS
BEGIN 
    IF (@p_name is null)
        RAISERROR 123456 'why are you null'
    ELSE  
        INSERT INTO dbo.persons(LastName) 
        VALUES(@p_name)
END

我是这样从Delphi调用上述过程的:

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    ADOStoredProc1.Parameters.ParamByName('@p_id').Value := 10;
    ADOStoredProc1.ExecProc; // error why are you null
  except
   on E: EDatabaseError do
     ShowMessage(e.Message);
  end;
end;

在Delphi代码中,我没有传递第二个参数,并且我希望SQL Server应该使用它的默认值。

当我执行存储过程时,我得到了一个错误。 当我未从Delphi传递任何内容时,为什么SQL Server不采用默认值?

如果我将参数值设置为“虚拟”,则它按预期工作。 在此处输入图片说明

TL; DR-要使用默认的SP参数值集,请执行以下操作:

ADOStoredProc1.Parameters.ParamByName('@p_name').ParameterObject.Value := Unassigned

在Delphi代码中, 我没有传递第二个参数,并且我希望SQL Server应该使用它的默认值。

是的,你是。 您在设计时使用的参数已经存在,因此该参数作为NULL显式发送到SQL Server。 您可以通过检查SQL事件探查器来验证这一点。

如果必须使用设计时参数,则每当要使用默认参数时都可以在运行时将其删除,否则可以创建/分配它。 例如(您可以为此创建一个通用方法):

var
  Param: TParameter;
  ParamName: WideString;
  ParamValue: Variant;
  UseDefaultParameter: Boolean;
begin
  ParamName := '@p_name';
  Param := ADOStoredProc1.Parameters.FindParam(ParamName);
  UseDefaultParameter := True; // or False to assign a value

  if UseDefaultParameter then
  begin
    if Assigned(Param) then
      ADOStoredProc1.Parameters.Delete(Param.Index);
  end
  else
  begin
    ParamValue := 'boo!';
    if Assigned(Param) then
      Param.Value := ParamValue
    else
      ADOStoredProc1.Parameters.CreateParameter(ParamName, ftString, pdInput, 10, ParamValue);
  end;
end;

否则,请勿使用设计时参数并在需要时在运行时创建参数。 IMO的一种更好的方法是使用本地TADOStoredProc ,在运行时创建它,分配参数,执行它并销毁它。

就个人而言,我在运行时创建TADOStoredProc并调用Parameters.Refresh()方法,该方法将从SQL Server中查询(并创建)参数。 然后我只需将值分配给所需的参数即可。 即使有额外的SQL Server行程,向SP添加新参数时也非常方便维护。
如果未设置参数值,则ADO将启动exec命令,以default关键字设置参数。

exec p_dummy_proc @p_id=1, @p_name=default

进一步挖掘之后,我注意到问题实际上出在TParameter.SetValue设置程序中。 无法“清除”参数值:

procedure TParameter.SetValue(const Value: Variant);
begin
  if VarIsEmpty(Value) or VarIsNull(Value) then <--
    NewValue := Null
  else
  begin
    ...
  end;  
  ParameterObject.Value := NewValue;
end;

您可以看到,如果将Value设置为NULLUnassigned ,则ParameterObject.Value将设置为NULL (但绝不会设置为默认值)。

因此,如果需要清除参数并使用默认值,则需要直接将TParameter.ParameterObject.Value设置为Unassigned

if UseDefaultParameter then 
  SP.Parameters.ParamByName('@p_name').ParameterObject.Value := Unassigned
else
  SP.Parameters.ParamByName('@p_name').Value := 'boo!'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM