7
votes

SQL Mise à jour des paramètres facultatifs PHP

Nous voulons changer la façon dont nous passons des valeurs de PHP aux procédures stockées (T-SQL). Je n'ai que une expérience mineure avec PHP, mais je tenterai d'expliquer le processus de discussions avec notre développeur Web.

processus actuel strong> p>

exemple de table d'essai p>

table d'essai p>

Pour mettre à jour un enregistrement, tel que le champ3 dans cet exemple, nous réussirions toutes les valeurs existantes à la procédure stockée. P>

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


4 commentaires

Je ne sais pas si je suis la question. Mais puisque vous passez des paramètres nommés dans votre exécution de la procédure stockée. EXEC DBO.UPTESTESTEST ID = 1, field2 = 'def', field3 = 'ghi' Vous envoyez des nulls à tous les autres champs. Vous n'avez pas besoin de faire quoi que la valeur sera nulle. Je ne réussirais pas une valeur de -999 car je ne vois aucun besoin. Qu'est-ce que vous écrivez dans la base de données, un null ou un -999?


Il n'y a rien de mal à votre "ce que nous aimerions passer". Si vous êtes sur le serveur MSSQL, différentes plates-formes SQL fonctionnent différemment.


J'ai posté dans la section de réponse en raison de l'utilisation de symboles @ il essaie de me bloquer si je les mettit dans la section Commentaires.


Pourriez-vous envelopper les paramètres dans XML et transmettre cela aux procédures. SQL Server peut analyser XML afin que toute combinaison de paramètres soit passée et analysée. Peut-être intéressant? Stackoverflow .Com / Questions / 15128999 / ... . Aussi: itworld.com/article/2960645/Développement/.../a>. Et: simple -Talk.com/blogs/.../a>


4 Réponses :


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

3 commentaires

Je ne sais pas si je comprends bien le problème. Mais je pense que la déclaration de mise à jour sera sur une valeur d'écrire une valeur avec un null s'il y avait déjà une valeur là-bas et rien n'a été envoyé à la procédure stockée. Si je vous comprends correctement, je pense que le côté PHP est correct, le problème est sur la procédure stockée.


Bien que cela soit correct, l'OP souhaite connaître le meilleur moyen de gérer la situation du moment où une valeur null est transmise et compréhension lorsque cela signifie mettre à jour la valeur à une mise à jour nulle ou non.


Mon point était de dire que je ne pense pas que la déclaration SQL fera cela. Il faudra dans une null et sur une valeur non nulle de la manière dont il est configuré. Je ne pense pas que la question ait quelque chose à voir avec le PHP. C'est la façon dont ils font le SQL. Ils devront peut-être faire une procédure stockée SQL dynamique si c'est ce qui est souhaité. Avoir un peu de mal à essayer de déchiffrer la question. Essayer d'aider mais pas sûr de comprendre ce qu'ils cherchent à faire dans les détails.



1
votes

Votre approche où vous utilisez un numéro magique -999 code> pour la valeur null code> a un problème, car toute approche avec des numéros magiques a. Pourquoi -999 code>? Pourquoi pas -999999 code>? Êtes-vous sûr que -999 code> ne peut pas être une valeur normale pour le champ? Même s'il n'est pas permis à un utilisateur d'entrer -999 code> pour ce champ maintenant, êtes-vous sûr que cette règle restera en place dans quelques années lorsque votre demande et votre base de données évoluent? Il ne s'agit pas d'être efficace ou non, mais d'être correct ou non.

Si vos champs de la table étaient pas NULL code>, vous pouviez passer une valeur de code code> null indiquer que ce champ ne doit pas être mis à jour. Dans ce cas, il est correct d'utiliser une valeur magique null code>, car le schéma de table garantit que le champ ne peut pas être null code>. Il y a une chance que le schéma de table change à l'avenir, donc null code> peut devenir une valeur valide pour un champ. P>

Quoi qu'il en soit, votre schéma actuel permet nulls code>, nous devrions donc choisir une autre approche. Avoir un indicateur explicite pour chaque champ qui indiquerait la procédure si le champ doit être mis à jour ou non. P>

SET @paramupdatefieldn code> à 1 lorsque vous souhaitez modifier la valeur de ce champ. La procédure utiliserait la valeur qui est transmise dans le @paramfieldn code>. P>

définir @paramupdatefieldn code> à 0 lorsque vous ne voulez pas modifier la valeur de ce champ. Ensemble @paramfieldn code> à n'importe quelle valeur (par exemple, null code>) et le champ correspondant de la table ne changera pas. P>

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


0 commentaires

0
votes

Pas assez de réputation pour simplement commenter. À mon avis, votre solution est suffisante tant que la valeur arbitraire ne peut être une valeur normale pour aucun des champs.

Cependant, j'envisagerais de passer et de stocker quelque chose d'autre à part Null ("N / A", par exemple) lorsqu'un champ ne doit pas avoir de valeur "réelle" et c'est à volontairement mises à jour du côté du client.


0 commentaires

2
votes

La méthode de Valdimir est excellente pour passer une variable de drapeau à identifier lorsque la valeur est transmise ou non passée et que ses notes sur la sélection arbitraire d'une valeur ont raison, mais je devinerais qu'il y a des valeurs arbitraires que vous n'avez peut-être jamais se préoccuper de. telle que -999 pour un entier lorsque vous ne permettez pas de chiffres négatifs, ou '|||||||' Pour une chaîne nulle. Bien sûr, cela décompose certains lorsque vous souhaitez utiliser des nombres négatifs, mais vous pouvez potentiellement jouer avec des chiffres trop gros pour un type de données tel que un paramètre par défaut -9223372036854775808 pour un ... Le problème vient vraiment Pour votre entreprise de savoir si des valeurs peuvent ou ne peuvent pas être autorisées.

Cependant, si vous allez un itinéraire comme ça, je suggérerais 2 choses. 1) Ne transmettez pas la valeur de PHP à SQL, faites plutôt que la valeur par défaut dans SQL et testez si le paramètre est la valeur par défaut. 2) Ajoutez une contrainte de vérification à la table pour vous assurer que les valeurs ne sont pas utilisées et ne peuvent pas être représentées dans le tableau p>

alors quelque chose comme: p> xxx pré>

le Le problème réel avec cette méthode est le champ de données numérique permettant aux nombres négatifs, car vous n'avez vraiment pas de manière appropriée de déterminer lorsque la valeur doit être nulle ou non à moins que vous ne puissiez choisir un nombre qui sera toujours hors de portée. Et je réalise définitivement à quel point une idée de l'exemple de Int l'exemple est parce que maintenant votre procédure acceptera une plage numérique qu'elle ne devrait pas! EM> P>

Une autre méthode / légère variation de La suggestion de Vladimir est de signaler quand faire un champ NULL plutôt que lorsque vous devez mettre à jour. Cela prendra un peu de s'habituer à votre équipe PHP pour vous rappeler de l'utiliser, mais parce que ces drapeaux peuvent également être facultatifs, ils ne doivent pas nécessairement être bourdonnés pour toujours inclure quelque chose comme: P>

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


0 commentaires