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

2024-02-21

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

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 不采用默认值?

if i set the parameter value to 'dummy' it is working as expected. enter image description here


TL;DR- 要使用默认 SP 参数值设置:

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

在德尔福代码中,我没有传递第二个参数我是 期望 SQL Server 应该采用它的默认值。

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

If you must使用设计时参数,您可以在运行时删除它default参数旨在以其他方式使用或创建/分配它。例如(你可以为此制定一个通用方法):

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() http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/ADODB_TParameters_Refresh.html方法,它将从 SQL Server 查询(并创建)参数。然后我只需将值分配给我需要的参数即可。即使多了一次SQL Server,但在SP中添加新参数时维护起来还是很方便的。
如果未设置参数值,ADO 将启动exec命令设置参数default关键词。 IE

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 to NULL or Unassigned, ParameterObject.Value将被设置为NULL(但永远不会使用默认值)。

所以如果需要清除某个参数,并使用默认值,则需要直接设置TParameter.ParameterObject.Value to Unassigned:

if UseDefaultParameter then 
  SP.Parameters.ParamByName('@p_name').ParameterObject.Value := Unassigned
else
  SP.Parameters.ParamByName('@p_name').Value := 'boo!'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TADOStoredProc 和 SQL Server 存储过程,参数作为默认值 的相关文章

随机推荐