update werkt niet bij een bepaald aantal tabelrijen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Andy Kort

Andy Kort

29/03/2019 10:36:03
Quote Anchor link
Goedemorgen,

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.
 
PHP hulp

PHP hulp

28/11/2024 16:58:11
 
- Ariën  -
Beheerder

- Ariën -

29/03/2019 10:49:58
Quote Anchor link
Hebben we het echt over 130 records/items/rijen of over kolommen?
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 -
 
Andy Kort

Andy Kort

29/03/2019 11:14:34
Quote Anchor link
We hebben het over 130 records in een tabel van ongeveer 10 kolommen (datum, tijd en kleine teksten e.d.).

Ik ga met die mysqli_error aan de slag. Bedankt.
 
Thomas van den Heuvel

Thomas van den Heuvel

29/03/2019 15:43:16
Quote Anchor link
Is toevallig het auto-increment id te klein? Daarbij, als dit geen unsigned integer is gooi je sowieso al ongeveer de helft van de beschikbare nummers weg omdat auto-increment id's niet negatief kunnen zijn.

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
 
Andy Kort

Andy Kort

29/03/2019 16:14:10
Quote Anchor link
Het ID heb ik 5 cijfers gemaakt en unsigned toegevoegd. Geen resultaat. Het formulier dat verstuurd wordt is opgebouwd uit de tabelrecords. Voor iedere regel is een checked opgenomen. Wanneer deze is aangevinkt kan dat record direct in de tabel worden aangepast. Door de verzendknop wordt het totaal verstuurd en wordt de querie uitgevoerd. Dit werkt prima tot kennelijk een beperkt aantal records.

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.
 
Adoptive Solution

Adoptive Solution

29/03/2019 16:24:08
Quote Anchor link
Ziet je FORM er zo uit? Maar dan 130 regels ipv 5.

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?
 
Andy Kort

Andy Kort

29/03/2019 16:48:02
Quote Anchor link
Dat klopt. Je voorbeeld is vergelijkbaar. Met de print_r($_POST) wordt de hele Dbase als array weergegeven
 
Adoptive Solution

Adoptive Solution

29/03/2019 17:04:03
Quote Anchor link
Je moet dan door die array gaan en elk record updaten.

Hier de code uit het voorbeeld (alleen de vinkjes worden bewaard) :

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
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);
    }

}


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)
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
$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   );
";


Ik gebruik het af en toe om een duizend records per keer toe te voegen of bij te werken.
 
- Ariën  -
Beheerder

- Ariën -

29/03/2019 17:18:11
Quote Anchor link
Maar als je 130 rijen invoegt, en je vergeet ergens een vinkje, dan mis je weer een update. Zelf zou ik een hele waslijst aan records opsplitsen in losse pagina's d.m.v. een paginate-script.

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)
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
<?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>";
?>
Gewijzigd op 29/03/2019 17:26:52 door - Ariën -
 
Thomas van den Heuvel

Thomas van den Heuvel

29/03/2019 19:49:03
Quote Anchor link
Uhm. 130 records x 10 velden. Qua POST data zou dat geen enkel probleem moeten vormen? Ik zou dan eerder denken aan een andere bottleneck zoals bijvoorbeeld PHP-instellingen als max_input_vars of post_max_size ofzo. Of je code moet wel heel erg brak in elkaar zitten.

Maar het blijft koffiedik kijken zonder concrete code.
 
- Ariën  -
Beheerder

- Ariën -

29/03/2019 20:32:41
Quote Anchor link
Volgens mij staat dit standaard in PHP op 1000. Dus dan kom je uit op 1300 velden...
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 -
 
Thomas van den Heuvel

Thomas van den Heuvel

29/03/2019 20:42:14
Quote Anchor link
Hangt er ook vanaf wat je allemaal tegelijkertijd wilt bewerken. Dit doe je zelden tot nooit met een compleet ledenbestand.

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
 
- Ariën  -
Beheerder

- Ariën -

29/03/2019 20:50:00
Quote Anchor link
Misschien iets van betalingen afvinken, of iets dergelijks. Maar dan is het onzinnig om alles te updaten.
Daarom is het handig om een diff'je te trekken over de POST en diens gelijkliggende arraystructuur uit de database.
 
Thomas van den Heuvel

Thomas van den Heuvel

29/03/2019 22:09:47
Quote Anchor link
Maar zelfs dat doe je niet in bulk, tenzij je dat geautomatiseerd doet :p.
 
- Ariën  -
Beheerder

- Ariën -

29/03/2019 22:13:37
Quote Anchor link
Het gaat juist prima bij het bijhouden van lijsten. Het trekken van een diff'je bespaart het aantal queries.
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. ;-)
 
Thomas van den Heuvel

Thomas van den Heuvel

30/03/2019 13:37:02
Quote Anchor link
- Ariën - op 29/03/2019 17:18:11:
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
<?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>";
?>

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)
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
<?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
(
)
*/

?>

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
 
Andy Kort

Andy Kort

30/03/2019 15:14:33
Quote Anchor link
Iedereen bedankt voor het meedenken. Ik ga er vanuit dat hier het probleem ligt: max_input_vars.

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.
 
- Ariën  -
Beheerder

- Ariën -

30/03/2019 15:29:48
Quote Anchor link
Als je tegen de max_input_vars aanloopt, dan moet je hiervan een error te zien krijgen, of deze uit de logs kunnen vissen.

Ikzelf raad aan om het aantal velden te minimaliseren, en iets van een pagina-navigatie inbouwen.
 
Andy Kort

Andy Kort

26/07/2019 12:15:14
Quote Anchor link
Pagination ingebouwd en daarmee het probleem opgelost.
 
- Ariën  -
Beheerder

- Ariën -

26/07/2019 12:36:37
Quote Anchor link
Altijd een goed idee! :-)
 
Thomas van den Heuvel

Thomas van den Heuvel

26/07/2019 13:04:41
Quote Anchor link
Hoe je een applicatie vormgeeft hangt sterk af van de aard van de informatie, en hoe je deze wilt bewerken.

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
 

Pagina: 1 2 volgende »



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.