Mysqli meerdere rijen updaten in 1 query.
-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)
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
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";
}
}
?>
$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
Code (php)
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
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.';
}
?>
// 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()!
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.
Als jullie hem mooi vinden en eventuele bugs eruit zijn kan ik hem wel in het script gedeelte zetten denken jullie niet?
Code (php)
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
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";
}
}
?>
# 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";
}
}
?>
Quote:
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.De uitgebreide versie slaat bitwaardes op in de database
Zend heeft een fraaie ACL-oplossing beschikbaar gesteld, dat lijkt mij al snel een factor 10 beter bruikbaar.
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
ACL of RBAC, daar kun je wat mee, dat is te beheren.
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