2017-11-08 40 views
2

私はDelphi 7とSQL Server 2008を使用しています。以下に示すように、私はダミーテーブルとダミーストアドプロシージャを作成しました。TADOStoredProcとSQL Serverストアドプロシージャのデフォルト値を

私はこのようなデルファイから上記の手順を呼び出しています
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; 

、私は2番目のパラメータを渡していないと私は、SQL Serverは、それはデフォルト値です取る必要があることを期待しています。

ストアドプロシージャを実行すると、エラーが発生します。 Delphiから何も渡さなかったときにSQL Serverがデフォルト値を使用しないのはなぜですか?

「ダミー」にパラメータ値を設定すると、期待どおりに動作しています。 enter image description here

+0

あなたは正確に取得しているエラーは何ですか? – kirchner

+0

@kirchner:質問をエラーで更新しました。エラーは "なぜあなたはヌルですか?"です。 – DelphiLearner

+0

@nil ::私はパラメータのバインドされたプロパティを見ませんでした。 – DelphiLearner

答えて

4

TL; DR - デフォルトSPパラメータ値のセットを使用するには:Delphiコードで

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

をI 2番目のパラメータを通過しないと私は 午前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はdefaultキーワードを使用してパラメータを設定するexecコマンドを開始します。すなわち

exec p_dummy_proc @p_id=1, @p_name=default 

はさらに掘削した後、私はこの問題は、TParameter.SetValueセッターに実際にあることに気づきました。あなたはNULLまたはUnassignedValueを設定する場合には、ParameterObject.ValueNULLに設定されていることがわかります

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

(しかし、決してデフォルトの):そこに「クリア」パラメータ値に方法はありません。

あなたはパラメータをクリアし、デフォルト値を使用する必要があるのであれば、あなたは直接UnassignedTParameter.ParameterObject.Valueを設定する必要があります。

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

V.良い、有益な答え+1 – MartynA

+0

最後の編集'ParameterObject.Value:= Unassigned'は基本的には' Parameter.Value = Nothing'と同じですが、この質問を見ると.NETで見つけましたが、私は 'TParameter '。 – nil

+0

@nil、私は' Parameters.Refresh'を呼び出してそれを認識し、 'ParameterObject'を含むパラメータを検査しました。パラメータ値を"クリア "する何かがあることがわかりました。 – kobik

関連する問題