2016-08-15 14 views
7

PHPからストアドプロシージャ(T-SQL)に値を渡す方法を変更したいと考えています。私はわずかなPHPの経験しか持っていませんが、Web開発者との議論からそのプロセスを説明しようとします。SQL更新オプションパラメータPHP

現在のプロセス

例テストテーブル

Test table

この例では、このようなフィールド3のようなレコードを更新するために、我々は戻って、ストアドプロシージャにすべての既存の値を渡すことになります。

EXEC dbo.UpdateTest @ID = 1, @Field1 = 'ABC', @Field2 = 'DEF', @Field3 = 'GHI', @Field4 = 'JKL' 

Field3を更新するには、ボタンをクリックする必要があります。これにより、ストアドプロシージャを実行してデータを更新する新しいページに移動します。新しいページは値を認識しないので、UPDATEを実行する前に値を取得するためにSELECTプロシージャを実行する必要があります。

スクリプトは、更新されたデータをリロードするページにユーザーをリダイレクトし、変更が画面に反映されます。私たちがやりたい何

新しいプロセス

は、我々が変更したいフィールドを渡しています。

EXEC dbo.UpdateTest @ID = 1, @Field2 = 'DEF', @Field3 = 'GHI' 

私たちの解決方法は簡単です。最初に、すべての更新可能フィールドをオプションに設定します(NULLを渡すことができます)。次に、パラメータがNULL(渡されていない)かどうかを確認し、無視する場合は無視し、更新しない場合は更新します。

UPDATE 
    dbo.Test 
SET 
    Field1 = NULLIF(ISNULL(@Field1,Field1),'-999') 
    ,Field2 = NULLIF(ISNULL(@Field2,Field2),'-999') 
    ,Field3 = NULLIF(ISNULL(@Field3,Field3),'-999') 
    ,Field4 = NULLIF(ISNULL(@Field4,Field4),'-999') 
WHERE 
    ID = @ID 

我々はまだNULLを渡された場合の手順はNULLにデータベースレコードを更新したいが。この問題を回避するには、NULL(この場合は-999)に任意の値を代入して、任意の値(-999)が渡された場合にプロシージャがNULLを更新するようにしました。

このソリューションは、私の目では、問題を解決するにはかなり面倒です。もっと良い解決策はありますか?私たちは何を間違っていますか?

+0

質問に従うかどうかわかりません。しかし、ストアドプロシージャの実行時に名前付きパラメータを渡しているためです。 EXEC dbo.UpdateTest ID = 1、Field2 = 'DEF'、Field3 = 'GHI' 他のすべてのフィールドにnullを送信しています。値がnullになることは何もする必要はありません。私はそれのための必要性を見ないので、私は-999の値を渡すことはありません。 データベースには何を書いていますか?ヌルか-999ですか? –

+0

「私たちは何を渡したいのですか」という行には何も問題はありません。 MsSqlサーバー上にある場合、異なるSQLプラットフォームは異なる動作をします。 –

+0

@記号の使用のために私は答えのセクションに投稿しました。私がコメントのセクションに置くとブロックしようとします。 –

答えて

0
EXEC dbo.UpdateTest @ID = 1, @Field1 = 'ABC', @Field2 = 'DEF', @Field3 = 'GHI', @Field4 = 'JKL' 

EXEC dbo.UpdateTest @ID = 1, @Field2 = 'DEF', @Field3 = 'GHI' 

任意の回答に事前に巨大なおかげでMSSQLまたはSybaseと同じストアドプロシージャを使用するために、両方の有効な方法です。値を送信しない場合は、nullを送信するのと同じです。ストアドプロシージャにデフォルトを設定しない限りその場合、nullの代わりにデフォルトが使用されます。

+0

問題を完全に理解しているかどうかわかりません。しかし、私はあなたが既に値があって、何もストアドプロシージャに送られなかった場合には、ステートメントを更新することがnullで値を書き込むことになると思います。私が正しく理解していれば、PHP側が正しいと思います。問題はストアドプロシージャ側にあります。 –

+0

これが正しい間に、OPは、null値が渡されたときの状況を処理する最良の方法を知りたいときに、その値をnullに更新するか全く更新しないことを意味するのかを理解したいと考えています。 – Matt

+0

私の主張は、SQL文がそれを行うとは思わないと言いました。これは、ヌル値とヌル値が設定された方法で書き込みます。私は問題は、PHPとは関係がないとは思わない。彼らはSQLをやっている方法です。彼らはそれが望ましい場合は、動的SQLストアドプロシージャを行う必要があります。質問を解読しようとするのが少し難しい。助けようとしていますが、私は彼らが細部でやろうとしていることを理解しています。 –

1

NULLの値にマジックナンバー-999を使用するあなたのアプローチは、マジックナンバーのアプローチには問題があります。なぜ-999ですか?どうしてですか?-999999-999はフィールドの通常の値ではないと確信していますか?ユーザーがこのフィールドに-999と入力することはできませんが、アプリケーションとデータベースが進化してから数年後にこのルールが有効になっていますか?効率的かどうかではなく、正しいかどうかについてです。

テーブル内のフィールドがNOT NULLだった場合は、このフィールドを更新しないことを示すNULLの値を渡すことができます。この場合、マジック値NULLを使用しても問題ありません。これは、テーブルスキーマによってフィールドがNULLにならないことが保証されているためです。テーブルスキーマが将来変更される可能性があるので、NULLがフィールドの有効な値になる可能性があります。

とにかく、現在のスキーマにはNULLsが許されているので、別のアプローチを選択する必要があります。フィールドを更新するかどうかをプロシージャに指示する明示的なフラグを各フィールドに付けます。

このフィールドの値を変更する場合は、@ParamUpdateFieldNを1に設定します。プロシージャは、対応する@ParamFieldNで渡された値を使用します。

このフィールドの値を変更しない場合は、@ParamUpdateFieldNを0に設定します。 @ParamFieldNに任意の値(たとえば、NULL)を設定すると、テーブル内の対応するフィールドは変更されません。

CREATE PROCEDURE dbo.UpdateTest 
    -- Add the parameters for the stored procedure here 
    @ParamID numeric(10,0),     -- not NULL 

    -- 1 means that the field should be updated 
    -- 0 means that the fleld should not change 
    @ParamUpdateField1 bit,     -- not NULL 
    @ParamUpdateField2 bit,     -- not NULL 
    @ParamUpdateField3 bit,     -- not NULL 
    @ParamUpdateField4 bit,     -- not NULL 

    @ParamField1 nvarchar(250),    -- can be NULL 
    @ParamField2 nvarchar(250),    -- can be NULL 
    @ParamField3 nvarchar(250),    -- can be NULL 
    @ParamField4 nvarchar(250)    -- can be NULL 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 
    SET XACT_ABORT ON; 

    BEGIN TRANSACTION; 
    BEGIN TRY 

     UPDATE dbo.Test 
     SET 
      Field1 = CASE WHEN @ParamUpdateField1 = 1 THEN @ParamField1 ELSE Field1 END 
      ,Field2 = CASE WHEN @ParamUpdateField2 = 1 THEN @ParamField2 ELSE Field2 END 
      ,Field3 = CASE WHEN @ParamUpdateField3 = 1 THEN @ParamField3 ELSE Field3 END 
      ,Field4 = CASE WHEN @ParamUpdateField4 = 1 THEN @ParamField4 ELSE Field4 END 
     WHERE 
      ID = @ParamID 
     ; 

     COMMIT TRANSACTION; 
    END TRY 
    BEGIN CATCH 
     -- TODO: process the error 
     ROLLBACK TRANSACTION; 
    END CATCH; 

END 

ので、手続きのパラメータはオプションではありませんが、あなたは有用な値を保持しているパラメータは無視されるべきパラメータを示すために、@ParamUpdateFieldNフラグを使用します。

0

コメントするだけの評判は不十分です。 私の意見では、あなたの解決策は、任意の値が任意のフィールドの通常の値になることができない限り十分です。

しかし、フィールドに「実際の」値を持たず、クライアント側から意図的に更新する必要がある場合は、NULL以外のもの(たとえば "N/A"など)以外のものを渡して保存することを検討します。

2

Valdimirの方法は、値が渡されたときと渡されなかったときを識別するためのフラグ変数を渡していて、任意の値を選んだというメモが正しいときには素晴らしいですが、決してあるかもしれない任意の値があると思います心配する必要があります。負の数を許さない場合は整数の場合は-999、 '||||||' null文字列の場合もちろん、これは負の数を使用したいときにはいくつかの問題を引き起こしますが、BIGINTなどのデータ型では数値が大きすぎて、デフォルトのパラメータとして-9223372036854775808のintを再生する可能性があります。値を許可することができるかどうかをビジネスケースに反映します。

しかし、あなたがそのようなルートを行くなら、私は2つのことをお勧めします。 1)PHPからSQLへの値を渡すのではなく、SQLのデフォルト値にして、そのパラメータがデフォルト値であるかどうかをテストします。 2)の値が使用されていないことを確認するために、テーブルにチェック制約を追加し、テーブル

で表現することはできませんので、何かのように:

ALTER TABLE dbo.UpdateTest 
CHECK CONSTRAINT chk_IsNotNullStandInValue (Field1 <> '|||||||||||||||||||' AND Field2 <> -999) 

CREATE PROCEDURE dbo.UpdateTest 
    @ParamId numeric(10,0) 
    ,@ParamField1 NVARCHAR(250) = '|||||||||||||||||||' 
    ,@ParamField2 INT = -99999 --non negative INT 
    ,@ParamField3 BIGINT = -9223372036854775808 --for an int that can be negative 
AS 
BEGIN 

DECLARE @ParamField3Value INT 

BEGIN TRY 

    IF ISNULL(@ParamField3,0) <> -9223372036854775808 
    BEGIN 
     SET @ParamField3Value = CAST(@ParamField3 AS INT) 
    END 
END TRY 
BEGIN CATCH 
    ;THROW 51000, '@ParamField3 is not in range', 1 
END CATCH 

    UPDATE dbo.Test 
     SET Field1 = IIF(@ParamField1 = '|||||||||||||||||||',Field1,@ParamField1) 
      ,Field2 = IIF(@ParamField2 = -99999,Field2,@ParamField2) 
      ,Field3 = IIF(@ParamField3 = -9223372036854775808, Field3, @ParamField3Value) 
    WHERE 
     ID = @ParamId 

END 

この方法での本当の問題は可能数値データフィールドであります負の数の場合は、常に範囲外になる数値を選択できない限り、値がいつnullになるかを判断する適切な方法がありません。 そして、私は間違いなく、あなたの手続きが数値ではないはずの数値を受け入れるので、BIGINT INTの例がどれほど悪いのかが分かります!

もう1つの方法/わずかなバリエーションは、更新するときではなくフィールドをnullにするときにフラグを立てることです。あなたが基本的にあれば

CREATE PROCEDURE dbo.UpdateTest 
    @ParamId numeric(10,0) 
    ,@ParamField1 NVARCHAR(250) = NULL 
    ,@MakeField1Null BIT = 0 
    ,@ParamField2 INT = NULL 
    ,@MakeField2Null BIT = 0 
    ,@ParamField3 INT = NULL 
    ,@MakeField3Null BIT = 0 
AS 
BEGIN 

    UPDATE dbo.Test 
     SET Field1 = IIF(ISNULL(@MakeField1Null,0) = 1,NULL,ISNULL(@ParamField1,Field1)) 
      ,Field2 = IIF(ISNULL(@MakeField2Null,0) = 1,NULL,ISNULL(@ParamField2,Field2)) 
      ,Field3 = IIF(ISNULL(@MakeField3Null,0) = 1,NULL,ISNULL(@ParamField3,Field3)) 
    WHERE 
     ID = @ParamId 

END 

:これはいつものようなものを含める使用することを覚えておくことが、これらのフラグはまた、オプションのことができるので、彼らはに負担する必要はありません、あなたのPHPのチームのために慣れる少しかかりますテーブルを更新するためにストアドプロシージャを使用していて、フィールドに空値がある場合は、数値データ型に関して将来的に乱雑になりうるビジネスケース/状況につながるので、パラメタをオプションにすることをおすすめしません。