2009-12-14 11 views
3

J'essaie de comprendre les procédures stockées MySQL, je veux vérifier si un utilisateur de références de connexion sont valides et si oui, mettez à jour les utilisateurs statut en ligne:Utiliser SELECT pour exécuter resultset UPDATE requête avec MySQL Procédures stockées

-- DROP PROCEDURE IF EXISTS checkUser; 
DELIMITER // 
CREATE PROCEDURE checkUser(IN in_email VARCHAR(80), IN in_password VARCHAR(50)) 
BEGIN 
    SELECT id, name FROM users WHERE email = in_email AND password = in_password LIMIT 1; 
    -- If result is 1, UPDATE users SET online = 1 WHERE id = "result_id"; 
END // 
DELIMITER ; 

Comment puis-je faire cette instruction si-basée sur le nombre de résultats resultsets == 1 ou ID IS NOT NULL?

Répondre

7
DELIMITER // 
CREATE PROCEDURE checkUser(IN in_email VARCHAR(80), IN in_password VARCHAR(50)) 
BEGIN 
    DECLARE tempId INT DEFAULT 0; 
    DECLARE tempName VARCHAR(50) DEFAULT NULL; 
    DECLARE done INT DEFAULT 0; 

    DECLARE cur CURSOR FOR 
     SELECT id, name FROM users WHERE email = in_email AND password = in_password; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 

    OPEN cur; 

    REPEAT 
     FETCH cur INTO tempId, tempName; 
     UPDATE users SET online = 1 WHERE id = tempId; 
    UNTIL done = 1 END REPEAT; 
    CLOSE cur; 

    SELECT tempName; 
END // 
DELIMITER ; 

NB: Je n'ai pas testé. Il est possible que MySQL n'aime pas UPDATE par rapport à une table pour laquelle un curseur est ouvert. PS: Vous devriez reconsidérer how you're storing passwords.


Re commentaires sur RETURN par rapport OUT par rapport à un jeu de résultats:

RETURN est utilisé que dans les fonctions stockées, pas les procédures stockées. Les fonctions stockées sont utilisées lorsque vous souhaitez appeler la routine dans une autre expression SQL.

SELECT LCASE(checkUserFunc(?, ?)); 

Vous pouvez utiliser un paramètre OUT, mais vous devez déclarer une variable d'utilisateur premier à passer pour ce paramètre. Et puis vous devez sélectionner cette variable utilisateur pour obtenir sa valeur de toute façon.

SET @outparam = null; 
CALL checkUser(?, ?, @outparam); 
SELECT @outparam; 

Lors du retour des jeux de résultats à partir d'une procédure stockée, il est plus facile d'utiliser une requête SELECT.

+0

@Bill: Y at-il un avantage à utiliser SELECT vs RETURN ou les paramètres OUT? –

+0

Le premier code de cette réponse fonctionne très bien, merci pour la réponse. Il a fallu du temps pour comprendre mais maintenant j'ai compris. :-) À l'heure actuelle, je crypte mes mots de passe (pas MD5 et à sens unique) trois fois et deux d'entre eux en utilisant différents sels et en utilisant différentes méthodes de cryptage, donc je pensais que ce serait suffisant. Une telle corde me semble vraiment difficile à bruteforce.Ces choses semblaient être un résumé du lien que vous m'avez donné. Y avait-il autre chose que vous pensiez? – Tirithen

+0

Non, si vous utilisez une fonction de hachage forte et un sel aléatoire par utilisateur, cela devrait suffire. Je craignais que vous stockiez des mots de passe en texte brut puisque vous ne faisiez que comparer le mot de passe in_password au champ de la base de données avec l'opérateur '='. À votre santé! –

2

Utilisation:

UPDATE USERS 
    SET online = 1 
WHERE EXISTS(SELECT NULL 
       FROM USERS t 
       WHERE t.email = IN_EMAIL 
       AND t.password = IN_PASSWORD 
       AND t.id = id) 
    AND id = 'result_id' 

Pourquoi avez-vous sur votre LIMIT 1 SELECT? Est-ce que vous vous attendez vraiment à ce qu'un email et un mot de passe soient dans la base de données plus d'une fois?

+0

Merci pour la réponse rapide et oui, LIMIT 1 est inutile, je vais supprimer celui-là. Encore une chose, je veux retourner le nom de l'utilisateur (de la sous-requête SELECT) au script PHP. Comment puis-je définir une variable "return" ou créer un jeu de résultats de retour de la sous-requête? – Tirithen

+0

@Tirithen: Vous pouvez utiliser la clause RETURN ou utiliser un paramètre IN OUT. Le paramètre OUT signifie que vous fournissez un paramètre à la requête, il doit/doit être rempli et vous pouvez utiliser le paramètre par la suite. Je vais mettre à jour avec plus d'informations plus tard, mais pour l'instant, voir: http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html –

0

Vous pouvez essayer une instruction if si vous avez un résultat qui renvoie 1 i regardé code yor, il semble que rien ne retourne vrai si vous devez refactoriser, comme ci-dessus omg a écrit des thats vraiment vrai pourquoi vous avoir une limite 1 dans votre requête select où une seule adresse email peut exister? quelque chose comme ça

update users set if(result==1,online=1,online=0) where email=emailadress