update werkt niet bij een bepaald aantal tabelrijen
Ik heb een applicatie gemaakt, bestaande uit 1 tabel. Hieraan zit o.a. een updatefunctie gekoppeld. Alles werkt prima, tot de tabel meer dan ongeveer 130 rijen groot wordt. De updatefunctie doet dan niets meer. Geen idee waar ik het zoeken moet (ben hobbyprogrammeur).
Kan ik ergens een instelling aanpassen? bv. in phpadmin?
Bedankt alvast.
Een tabel met 130 kolommen klinkt mij namelijk in de oren als een zeer complexe datastructuur die je liever wilt normaliseren, en waar uiteindelijk je op zou kunnen vastlopen door de complexiteit.
Of heb je het echt over records? Ik kan me niet indenken dat 130 records dan een bottleneck kan vormen. Een tabel kan met gemak miljoenen records aan.
De vraag is: Wat gebeurt er precies, en wat meldt de foutafhandeling bijvoorbeeld met mysqli_error? Ga dat eerst eens onderzoeken.
Gewijzigd op 29/03/2019 10:51:02 door - Ariën -
Ik ga met die mysqli_error aan de slag. Bedankt.
EDIT: hm, hoe ziet de structuur er uit, en wat gebeurt er tijdens het updaten?
Gewijzigd op 29/03/2019 15:53:12 door Thomas van den Heuvel
Ik weet niet of dat kan, maar ik heb de indruk dat het formulier te groot wordt om te verwerken. Ik heb mysqli_error ingezet om een reactie te krijgen, maar dat gebeurt niet. Kennelijk wordt heel de verbinding/querie niet bereikt.
http://adoptive.2kool4u.net/members/
Zou betekenen dat je complete DB in een $_POST wordt verstuurd.
Wat zie je, uit nieuwsgierigheid, als je een print_r($_POST) doet?
Dat klopt. Je voorbeeld is vergelijkbaar. Met de print_r($_POST) wordt de hele Dbase als array weergegeven
Hier de code uit het voorbeeld (alleen de vinkjes worden bewaard) :
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
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
if( isset( $_POST['Submit'] ) ) {
$count = count( $_POST['id'] );
$count_present = count( $_POST['present'] );
for( $i = 0 ; $i < $count ; $i++ ){
$id = $db->real_escape_string( $_POST['id'][$i] );
$full_name = $db->real_escape_string( $_POST['full_name'][$i] );
$email = $db->real_escape_string( $_POST['email'][$i] );
$age = $db->real_escape_string( $_POST['age'][$i] );
$present = 0;
for( $y = 0 ; $y < $count_present ; $y++ ) {
if ( $_POST["present"][$y] == $id ) {
$present = 1;
break;
}
}
// in demo wordt alleen present bewaard. andere velden niet
$query = "
UPDATE
$tbl_name
SET
present = '" . $present . "'
WHERE
id = '" . $id . "'";
$db->query($query);
}
}
$count = count( $_POST['id'] );
$count_present = count( $_POST['present'] );
for( $i = 0 ; $i < $count ; $i++ ){
$id = $db->real_escape_string( $_POST['id'][$i] );
$full_name = $db->real_escape_string( $_POST['full_name'][$i] );
$email = $db->real_escape_string( $_POST['email'][$i] );
$age = $db->real_escape_string( $_POST['age'][$i] );
$present = 0;
for( $y = 0 ; $y < $count_present ; $y++ ) {
if ( $_POST["present"][$y] == $id ) {
$present = 1;
break;
}
}
// in demo wordt alleen present bewaard. andere velden niet
$query = "
UPDATE
$tbl_name
SET
present = '" . $present . "'
WHERE
id = '" . $id . "'";
$db->query($query);
}
}
Toevoeging op 29/03/2019 17:17:04:
In het voorbeeld wordt elk record apart geupdate.
Was toen niet bekend met "insert on duplucate update". Zou dat nu wel gebruiken.
http://www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/
Je moet dan de $_POST gaan bewerken in een query zoal dit :
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$query = "
INSERT INTO
students
(id, name, class, social, science, math)
VALUES
(2, 'Max Ruin', 'Three', 86, 57, 86),
(3, 'Arnold', 'Three', 56, 41, 76),
(4, 'Krish Star', 'Four', 62, 52, 72),
(5, 'John Mike', 'Four', 62, 82, 92),
(6, 'Alex John', 'Four', 58, 93, 83),
(7, 'My John Rob', 'Fifth', 79, 64, 74),
(8, 'Asruid', 'Five', 89, 84, 94),
(9, 'Tes Qry', 'Six', 77, 61, 71),
(10, 'Big John', 'Four', 56, 44, 56),
(11, 'New Name', 'Five', 75, 78, 52)
ON DUPLICATE KEY UPDATE
social = values( social ),
science = values( science),
math = values( math );
";
INSERT INTO
students
(id, name, class, social, science, math)
VALUES
(2, 'Max Ruin', 'Three', 86, 57, 86),
(3, 'Arnold', 'Three', 56, 41, 76),
(4, 'Krish Star', 'Four', 62, 52, 72),
(5, 'John Mike', 'Four', 62, 82, 92),
(6, 'Alex John', 'Four', 58, 93, 83),
(7, 'My John Rob', 'Fifth', 79, 64, 74),
(8, 'Asruid', 'Five', 89, 84, 94),
(9, 'Tes Qry', 'Six', 77, 61, 71),
(10, 'Big John', 'Four', 56, 44, 56),
(11, 'New Name', 'Five', 75, 78, 52)
ON DUPLICATE KEY UPDATE
social = values( social ),
science = values( science),
math = values( math );
";
Ik gebruik het af en toe om een duizend records per keer toe te voegen of bij te werken.
Zelf heb ik voor een dergelijk script de vinkjes afgeschaft en per stuk gekeken of er gepost is. Of nog mooier om de array's van je $_POST en al je items in je database met elkaar te vergelijken. En wijzigingen enkel door te voeren.
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
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
<?php
function array_diff_assoc_recursive($array1, $array2) {
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!isset($array2[$key])) {
$difference[$key] = $value;
} elseif (!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if ($new_diff != FALSE) {
$difference[$key] = $new_diff;
}
}
} elseif (!isset($array2[$key]) || $array2[$key] != $value) {
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
// loop de arrays recursief door en toon de verschillen.
$diff = array_diff_assoc_recursive($_POST['items'], $data);
// toon je de array
echo "<pre>".print_r($diff,1)."</pre>";
?>
function array_diff_assoc_recursive($array1, $array2) {
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!isset($array2[$key])) {
$difference[$key] = $value;
} elseif (!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if ($new_diff != FALSE) {
$difference[$key] = $new_diff;
}
}
} elseif (!isset($array2[$key]) || $array2[$key] != $value) {
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
// loop de arrays recursief door en toon de verschillen.
$diff = array_diff_assoc_recursive($_POST['items'], $data);
// toon je de array
echo "<pre>".print_r($diff,1)."</pre>";
?>
Gewijzigd op 29/03/2019 17:26:52 door - Ariën -
Maar het blijft koffiedik kijken zonder concrete code.
Dan kan het inderdaad een probleem vormen.
Daarom was 'pagination' juist handig, herinner ik me net na jouw post.
Dan beperk je het tot 25*10 velden, of je moet je max_input_vars verhogen, maar gebruikersvriendelijk gezien is opsplitsen over meerdere pagina's makkelijker in gebruik.
Gewijzigd op 29/03/2019 20:34:56 door - Ariën -
Ook over het doel van de code zou je het kunnen hebben, maar ik heb nog steeds geen code gezien.
Gewijzigd op 29/03/2019 22:08:48 door Thomas van den Heuvel
Daarom is het handig om een diff'je te trekken over de POST en diens gelijkliggende arraystructuur uit de database.
Maar zelfs dat doe je niet in bulk, tenzij je dat geautomatiseerd doet :p.
Het ligt meer aan de data die je beheert. Zo houd ik op deze manier een lijst van treinstel/-stamnummers en de status ervan bij.
Ik ben al blij dat ik geen single-page heb voor een treinstel/treinstam. ;-)
- Ariën - op 29/03/2019 17:18:11:
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
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
<?php
function array_diff_assoc_recursive($array1, $array2) {
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!isset($array2[$key])) {
$difference[$key] = $value;
} elseif (!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if ($new_diff != FALSE) {
$difference[$key] = $new_diff;
}
}
} elseif (!isset($array2[$key]) || $array2[$key] != $value) {
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
// loop de arrays recursief door en toon de verschillen.
$diff = array_diff_assoc_recursive($_POST['items'], $data);
// toon je de array
echo "<pre>".print_r($diff,1)."</pre>";
?>
function array_diff_assoc_recursive($array1, $array2) {
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!isset($array2[$key])) {
$difference[$key] = $value;
} elseif (!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$new_diff = array_diff_assoc_recursive($value, $array2[$key]);
if ($new_diff != FALSE) {
$difference[$key] = $new_diff;
}
}
} elseif (!isset($array2[$key]) || $array2[$key] != $value) {
$difference[$key] = $value;
}
}
return !isset($difference) ? 0 : $difference;
}
// loop de arrays recursief door en toon de verschillen.
$diff = array_diff_assoc_recursive($_POST['items'], $data);
// toon je de array
echo "<pre>".print_r($diff,1)."</pre>";
?>
Wat zou dit precies moeten doen? De oorspronkelijke array_diff(a, b[, c...]) functie bekijkt namelijk wat enkel in "a" voorkomt, en niet in "b", "c" et cetera. De vraag is of dit precies het verschil dekt (en wat betekent dit verschil precies? en hoe gebruik je dit?). En als dit niet in $_POST voorkomt, zou dit ook in kunnen houden dat er informatie verwijderd zou moeten worden, maar als die informatie afwezig is zul je dit alsnog in zijn geheel moeten spiegelen met de database-inhoud?
Let wel: array_diff() geeft dus mogelijk niet exact het verschil tussen twee arrays retour, maar alles wat verschilt ten opzichte van het eerste array (en dat is niet helemaal hetzelfde). Als dat recursieve ding op een soortgelijke wijze werkt is het misleidend als je het op de eerstgenoemde manier probeert te gebruiken.
Vergelijk:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$test1 = array('een', 'twee', 'drie');
$test2 = array('een');
echo '<pre>'.print_r(array_diff($test1, $test2), true).'</pre>';
/*
levert
Array
(
[1] => twee
[2] => drie
)
*/
echo '<pre>'.print_r(array_diff($test2, $test1), true).'</pre>';
/*
levert
Array
(
)
*/
?>
$test1 = array('een', 'twee', 'drie');
$test2 = array('een');
echo '<pre>'.print_r(array_diff($test1, $test2), true).'</pre>';
/*
levert
Array
(
[1] => twee
[2] => drie
)
*/
echo '<pre>'.print_r(array_diff($test2, $test1), true).'</pre>';
/*
levert
Array
(
)
*/
?>
Oftewel, array_diff() is niet commutatief.
Dan is er nog de mogelijke complicatie in bovenstaande implementatie met isset() in combinatie met NULL-waarden. isset() levert false op indien een variabele een NULL-waarde heeft. NULL-waarden kunnen mogelijk betekenis hebben in arrays, dus het lijkt mij onverstandig om deze op voorhand uit te sluiten. array_key_exists() lijkt mij een veiliger alternatief.
Maar los hiervan, ik zou eigenlijk nooit met verschillen werken maar gewoon alles leeggooien en opnieuw vullen in een database-transactie. Of gewoon een andere aanpak kiezen.
Topicstarter heeft ook nog steeds niet duidelijk gemaakt wat nu eigenlijk de bedoeling is. Daaruit moet nog blijken of de reeds ingeslagen weg wel een verstandige was. Het begint met een analyse, niet met een of andere knip-en-plak oplossing voor een onbekend probleem.
Gewijzigd op 30/03/2019 14:07:43 door Thomas van den Heuvel
Deze is max 1000 en ik krijg het via htaccess en php.ini niet aangepast en ga het dus bij de provider voorleggen.
Alle andere (scripts)oplossingen zijn heel mooi en daar ga ik ook wel mee aan de slag, alleen gaat me dat op dit moment teveel tijd kosten. Temeer omdat het systeempje prima draait tot ik tegen een limiet aan loop. Ik zal nog eentestversie aanmaken en daarbij het aantal te verwerken velden verminderen. Kijken wat er dan gebeurt.
Bedankt en goed weekend verder.
Ikzelf raad aan om het aantal velden te minimaliseren, en iets van een pagina-navigatie inbouwen.
Pagination ingebouwd en daarmee het probleem opgelost.
Altijd een goed idee! :-)
Zonder verdere informatie over wat deze informatie nu precies inhoudt lijkt het mij nogal voorbarig om te zeggen dat het in bulk behandelen van deze data en/of deze pagineren "altijd een goed idee" is. Misschien kom je met wat filters of sorteeropties verder dan simpelweg een paginering.
Ook kan ik mij weinig voorstellen bij het batchgewijs verwerken van data enkel op het criterium "X opeenvolgende records". Tenzij er op een specifieke manier gesorteerd wordt? Wederom, hier kan ik niets over zeggen omdat ik niets weet over de aard van de data.
Dan rijst dus ook de vraag of paginering ook echt de juiste oplossing is, of dat je daarmee enkel het directe probleem wegneemt waarbij het om een of andere reden niet mogelijk was om alles in één keer te verwerken (en Joost mag weten of dat ook echt wenselijk is).
Een alternatieve oplossing zou je bijvoorbeeld ook kunnen zoeken in de richting van het groeperen van data op grond van een kenmerk (categorie, soort, rol, type et cetera). Vervolgens kun je op dit kenmerk je data filteren, zodat je waarschijnlijk inzoomt op dat specifieke deel waarin je geïnteresseerd bent.
Het lijkt mij (extreem) foutgevoelig om elke keer (en ik heb nog steeds geen argument gehoord waarom dit ook echt noodzakelijk zou zijn) in bulk grote updates op informatie uit te voeren.
En als dit daadwerkelijk een soort van administratief systeem betreft waarbij dit nodig is dan hoop ik van harte dat je ook van database-transacties gebruik maakt. Want stel nu dat er halverwege zo'n batch iets misgaat, en je gebruikt geen transactie? Dat houdt dan in dat de helft van de relevante records is geupdate, en de andere helft niet?
Nu heb je nog relatief weinig records en is alles nog te overzien. Maar als je niet in een vroeg stadium alles zo aanpakt dat er niets/zo min mogelijk fout kan gaan dan heb je binnen de kortst mogelijke tijd een enorme hoeveelheid stront in je database zitten.
Laat ik het anders verwoorden: als je niet uitlegt:
- wat voor data het betreft
- hoe je deze wenst te bewerken
(- en waarom)
Dan kunnen wij je eigenlijk op geen enkele manier voorzien van goed advies over de vormgeving of aanpak.
Gewijzigd op 26/07/2019 13:06:49 door Thomas van den Heuvel