Mysqli meerdere rijen updaten in 1 query.

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Chris visser

chris visser

24/02/2009 00:12:00
Quote Anchor link
Hey mensen. Ik ben bezig met een query waarbij ik meerdere leden indeel in meerdere groepen. Simpel gezegt:

-Er is een ledenlijst
-In de database heeft elk lid een GroupID toegewezen gekregen
-Bij elk lid staat een selectbox waar een groep gekozen kan worden
-Bij de submit word met een foreachloop de info per gebruiker opgehaald

De bedoeling is nu om de informatie in de database up te daten dmv 1 query. Ik heb zelf ook een soortgelijke sql insert query gemaakt voor mijn rechtensysteem die werkt met eenzelfde loop:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
  $sql
= "
      INSERT INTO rightstable
    (
        ModuleID,
          GroupID,
          AccesLevel
    )
      VALUES  
  "
;
  $t = 0;
    $CountData = count($data); //Count values for inserting (rows)
    $iAdd = $CountData - 1; // Submitbutton = -1
  foreach($data AS $key => $value)
    {

        if($key != 'submit') //Filter submitbutton
      {    
        $t++;
        #last row has , (comma)
        if($iAdd != $t)
        {

        $sql.="('".$key['module']."', '".$key['group']."', '".$key['level']."'),";
        }

        else  //Last row without ,
        {
          $sql.="('".$key['module']."', '".$key['group']."', '".$key['level']."')";
      }
        
      }
  }

  if(!$RightResult = $mysqli->query($sql)) //Activate Query
  {
    trigger_error('Fout in query: '.$mysqli->error);
  }
    
  else
  {
    if($mysqli->affected_rows > 0)
    {

      echo "Records succesfully inserted into database";
    }
  }

?>


Ik wilde hetzelfde princiepe toepassen op een UPDATE statement maar deze zit jammer genoeg anders in elkaar en werkt dus niet omdat ik een WHERE met gebruiken zodat de juiste waardes worden upgedate.

Heeft 1 van jullie een voorbeeldje waarmee ik aan het werk kan? Het doel is om de query maar 1 keer uit te voeren.
Gewijzigd op 01/01/1970 01:00:00 door Chris visser
 
PHP hulp

PHP hulp

22/12/2024 12:14:12
 
Eddy E

Eddy E

24/02/2009 08:50:00
Quote Anchor link
Zelf zou ik het zo doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php

// tellers instellen
$t = 0;
$succesvol = 0;
$aantal_updates = count($data);

// alle waarden langslopen
foreach($data AS $key => $value)
    {

    // teller verhogen
    $t++;
    
    // filter de submit-knop
    if($key == 'submit')
        {

        continue;    
        }

        
    // query maken en uitvoeren
    $sql = "
        INSERT INTO rightstable
            (
            ModuleID,
            GroupID,
            AccesLevel
            )
        VALUES  
            (
            '"
.$key['module']."',
            '"
.$key['group']."',
            '"
.$key['level']."'
            )
        WHERE id = "
.$key['id']."
            "
;
        
    // uitvoeren (en controleren)
    if(!$RightResult = $mysqli->query($sql))
        {

        trigger_error('Fout in query: '.$mysqli->error);
        }
    
    else
        {
        if($mysqli->affected_rows == 0)
            {

            trigger_error('Geen updates gevonden: '.$mysqli->error);
            }

        else
            {
            // aantal succesvol tellen
            $succesvol++;
            }
        }    
    }


// aantal gelukt weergeven
if($succesvol == $aantal_updates)
    {

    echo 'Alle updates zijn gelukt';
    }

else
    {
    echo $succesvol . 'updates gelukt';
    echo ($aantal_updates - $succesvol) . ' updates mislukt.';
    }

?>


Ja, een query in de while. Met het voordeel dat niet alles gelijk mislukt als er 1 fout is.
Zo wordt het deel wat je doet kleiner.
Plus dat het wat 'specifieker' aangegeven kan worden wat er gebeurd.

Let op: als group, level en module getallen (ints) zijn, dan GEEN enkele haakjes gebruiken.

Wil je toch op een andere manier verder: kijk naar implode()!
 
Chris visser

chris visser

24/02/2009 11:57:00
Quote Anchor link
Ja ok, maar dan voert hij dus bij 200 leden 200 query's uit en dat is niet de bedoeling. Mijn bovenstaande INSERT query werkt perfect en het is de basis van een uitgebreidere versie die ik gemaakt heb.

De uitgebreide versie slaat bitwaardes op in de database en maakt dus alleen gebruik van integers. Ik kan heel makkelijk een rollbackfunctie toepassen omdat ik maar 1 query heb. Je kunt zelfs de loop in de query uitbreiden zodat je precies te zien krijgt welke waarde een foutmelding genereerd.

Maarja, nu de update query. Ik wil hetzelfde princiepe toepassen, maar dat is me nog niet gelukt. Het laatste wat ik wil doen is de updatequery in een loop plaatsen. Ik gebruik nog liever de truncate table query waarna ik alles dmv mijn mass insertquery opnieuw invoer. Dat kost minder tijd.
 
Chris visser

chris visser

24/02/2009 18:23:00
Quote Anchor link
Mensen , ik ben er eindelijk uit. Hieronder mijn updateloop in 1 query met uitleg.

Als jullie hem mooi vinden en eventuele bugs eruit zijn kan ik hem wel in het script gedeelte zetten denken jullie niet?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
    # UPDATE statement in variabele stoppen
    # GroupID is de kolom die aangepast word bij elke record.
    # UserID staat voor de record en is de Primary key.

  $sql = "
      UPDATE core_users SET GroupID = CASE UserID  
  "
;
    # Loop de geposte waardes
    # $data = $_POST maar dan beveiligt

    foreach($data AS $key => $value)
    {

      # Filter lege waardes en Submitbutton
    if(($value != "") && ($key != "UpdateList"))
        {

          # Hier staat het vervolg van de UPDATE query
            # $key is de geposte UserID en $value is de GroupID dus letterlijk vertaald:
            # WHEN gebruiker overeenkomt in database THEN zet de volgende waarde neer

       $sql.= " WHEN '".$key."' THEN '".$value."' ";
        }
    }

    # Beeindig de UPDATE query
    $sql.= " END ";
    # Voer de query uit
    # De uitvoer van de query's verschillen per systeem. In mijn geval werk ik met Mysqli/OOP

    if(!$RightResult = $mysqli->query($sql))
  {

    trigger_error('Fout in query: '.$mysqli->error);
  }
    
  else
  {
    if($mysqli->affected_rows > 0)
    {

          # Melding na succesvol invoeren van alle data
      echo "Records inserted";
    }
  }

?>
 
Frank -

Frank -

24/02/2009 18:27:00
Quote Anchor link
Quote:
De uitgebreide versie slaat bitwaardes op in de database
Vraag je even heel erg goed af of je dit wel wil. De dagelijkse praktijd heeft inmiddels uitgewezen dat dit een klein drama is, vooral voor diegene die het mag gaan onderhouden en beheren. Je hebt namelijk geen flauw idee of rechten nu wel of niet goed staan of dat er toevallig ergens in een weergave iets niet goed zit.

Zend heeft een fraaie ACL-oplossing beschikbaar gesteld, dat lijkt mij al snel een factor 10 beter bruikbaar.
 
Chris visser

chris visser

24/02/2009 18:31:00
Quote Anchor link
Maar de groepen worden in mijn geval niet ingevoerd maar dmv een selectbox gekozen. Je kan dus nooit verkeerde waardes krijgen.

Zolang je zorgt dat er geen foute dingen ingevult kunnen worden werkt dit toch perfect?

Heb geen ervaring, dus als je een goeie reden heb neem ik hem graag over ;P
 
Frank -

Frank -

24/02/2009 18:34:00
Quote Anchor link
Breek me de bek niet los! Heb ruim 3 jaar met deze ellende moeten werken, dat nooit meer. De problemen ontstaan wanneer er onduidelijkheid is over een bepaalde situatie, je kunt dan keer op keer gaan uitvogelen hoe een bitje nu precies staat en in welke situatie nu een bepaalde functionaliteit nu wel of niet werkt/hoort te werken.

ACL of RBAC, daar kun je wat mee, dat is te beheren.
 
Chris visser

chris visser

24/02/2009 18:52:00
Quote Anchor link
Ok ik geloof je hoor vergis je niet :P

Ik wil het alleen nu zelf ondervinden, want ik ben nu al veels te ver met mijn systeem om ermee te stoppen. Het werkt eigenlijk heel simpel en fouten zijn bij mij toch echt redelijk makkelijk te achterhalen.

Elke module heeft een rechtentabelletje op een pagina. Hier kan je per groep de rechten aanklikken. Stel dat je 4 verschillende rechten hebt bijvoorbeeld: --Bezoeken,
-Toevoegen,
-Aanpassen,
-Verwijderen

Dan krijg je een bitwaarde van 4 bits lang. Stel dat een groep alle rechten krijgt dan krijg je dus de bitwaarde 1111, en 1111 = 32 dus word in de database voor die gebruikersgroep en module als toegangslevel 32 gegeven.
Heeft de groep geen recht om dingen aan te passen dan krijg je 0111 als bitwaarde en 14 als waarde die je in de database invoert.

Omgekeerd kun je de waarde 14 uit de database halen en omzetten in een bitwaarde waardoor je precies kunt bepalen welke rechten de groep heeft over de module die op dat moment opgevraagt word.

Ik snap niet waarom het nu nog moeilijk moet zijn om een eventuele fout te achterhalen. Zou de fout bij het invoeren zitten, dan krijg je een foute waarde in je database. Zou de fout bij het rechtenbepalen zitten, dan krijg je dat de gebruiker geen recht heeft of juist wel. Kwestie van duidelijk scripten lijkt me :S
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.