web-dev-qa-db-ja.com

SQL ServerストアドプロシージャのNullableパラメーター

問題
次のスクリプトに値が提供され、次に以下のようなC#のセットアップ(またはSQL Server環境)を使用して実行された場合、データベースの値は更新されません。

ストアドプロシージャ:

-- Updates the Value of any type of PropertyValue
-- (Type meaining simple Value, UnitValue, or DropDown)
CREATE PROCEDURE [dbo].[usp_UpdatePropertyValue]
    @PropertyValueID int,
    @Value varchar(max) = NULL,
    @UnitValue float = NULL,
    @UnitOfMeasureID int = NULL,
    @DropDownOptionID int = NULL
AS
BEGIN   
    -- If the Property has a @Value, Update it.
    IF @Value IS NOT NULL
    BEGIN
        UPDATE [dbo].[PropertyValue]
        SET
            Value = @Value
        WHERE
            [dbo].[PropertyValue].[ID] = @PropertyValueID
    END
    -- Else check if it has a @UnitValue & UnitOfMeasureID
    ELSE IF @UnitValue IS NOT NULL AND @UnitOfMeasureID IS NOT NULL
    BEGIN
        UPDATE [dbo].[UnitValue]
        SET
            UnitValue = @UnitValue,
            UnitOfMeasureID = @UnitOfMeasureID
        WHERE
            [dbo].[UnitValue].[PropertyValueID] = @PropertyValueID          
    END
    -- Else check if it has just a @UnitValue
    ELSE IF @UnitValue IS NOT NULL AND @UnitOfMeasureID IS NULL
    BEGIN
        UPDATE [dbo].[UnitValue]
        SET
            UnitValue = @UnitValue
        WHERE
            [dbo].[UnitValue].[PropertyValueID] = @PropertyValueID  
    END
    -- Else check if it has a @DropDownSelection to update.
    ELSE IF @DropDownOptionID IS NULL
    BEGIN
        UPDATE [dbo].[DropDownSelection]
        SET
            SelectedOptionID = @DropDownOptionID
        WHERE
            [dbo].[DropDownSelection].[PropertyValueID] = @PropertyValueID
    END
END

以下のようにこのスクリプトを実行すると、値は更新されません。

実行例:

String QueryString = "EXEC [dbo].[usp_UpdatePropertyValue] @PropertyValueID, @Value, @UnitValue, @UnitOfMeasureID, @DropDownOptionID";
SqlCommand Cmd = new SqlCommand(QueryString, this._DbConn);

Cmd.Parameters.Add(new SqlParameter("@PropertyValueID", System.Data.SqlDbType.Int));
Cmd.Parameters.Add(new SqlParameter("@Value", System.Data.SqlDbType.Int));
Cmd.Parameters.Add(new SqlParameter("@UnitValue", System.Data.SqlDbType.Int));
Cmd.Parameters.Add(new SqlParameter("@UnitOfMeasureID", System.Data.SqlDbType.Int));
Cmd.Parameters.Add(new SqlParameter("@DropDownOptionID", System.Data.SqlDbType.Int));

Cmd.Parameters["@PropertyValueID"].Value = Property.Value.ID; // 1
Cmd.Parameters["@Value"].IsNullable = true;
Cmd.Parameters["@Value"].Value = DBNull.Value;
Cmd.Parameters["@UnitValue"].IsNullable = true;
Cmd.Parameters["@UnitValue"].Value = DBNull.Value;
Cmd.Parameters["@UnitOfMeasureID"].IsNullable = true;
Cmd.Parameters["@UnitOfMeasureID"].Value = DBNull.Value;
Cmd.Parameters["@DropDownOptionID"].IsNullable = true;
Cmd.Parameters["@DropDownOptionID"].Value = 2; // Current Value in DB: 3

詳細:

(C#コードまたはSQL Server環境を介して)実行を実行した後、dbo.DropDownSelection.SelectedOptionID。私は_dbo.DropDownSelection.SelectedOptionIDは、null不可であり、それを設定するために使用しているパラメーターは、null可能です(設定するとき、nullであってはなりません)。実行時の戻り値は0です。プロシージャの外でUpdateの1つを実行した場合、それらは完全に機能します。したがって、null可能型に関係しているのではないかと疑っています。

質問:

これは、ストアドプロシージャのパラメーターがnull値を許可し、設定しているフィールドがnull値を許可していないためでしょうか?

そうでない場合、それは何でしょうか?

17
Shelby115

PropertyValueIDとDropDownOptionIDを除くすべての引数にNullを渡しているようです。これらの2つの値のみがnullでない場合、IFステートメントは起動しないと思います。要するに、論理エラーがあると思います。

それ以外に、私は2つのことを提案します...

まず、NULLをテストする代わりに、if文でこの種の構文を使用します(より安全です)...

    ELSE IF ISNULL(@UnitValue, 0) != 0 AND ISNULL(@UnitOfMeasureID, 0) = 0

次に、各UPDATEの前に意味のあるPRINTステートメントを追加します。そうすれば、MSSQLでsprocを実行するときに、メッセージを見て、実際にどこまで到達しているかを確認できます。

10
Ash8087

パラメーターの値をDBNull.Valueに設定できます/すべきです。

if (variable == "")
{
     cmd.Parameters.Add("@Param", SqlDbType.VarChar, 500).Value = DBNull.Value;
}
else
{
     cmd.Parameters.Add("@Param", SqlDbType.VarChar, 500).Value = variable;
}

または、サーバー側をnullのままにして、パラメーターをまったく渡さないようにすることもできます。

0
user1040975