Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: MYSQL: Tietokannan päivitys

Sivun loppuun

stageradio [07.05.2009 20:54:25]

#

Hei taas.

Päätin aloittaa uuden aiheen koska vanha otsikko ei enää vastannut ongelmaa.
https://www.ohjelmointiputka.net/keskustelu/19091-mysql-virhe-left-join-kyselyssä

Tällä koodini tulostaa listan kappaleista ja soittolistoista sekä tiedon millä soittolistoilla kappale on hienoon checkbox taulukkoon. (Kiitos Metabolixin!)

kappale       main     hitti     hidas
poison         x        x
sweet child..  x        x
juupijuu                          x
nönnöö
jne..

Ongelmani on siis sellainen että nyt jos ruksin esimerkiksi kappaleen nönnöö mainiin ja kappaleen juupijuu hitiksi, pitäisi saada myös tiedot tallennettua tietokantaan.

tiedot ovat kolmessa eri tietokannassa seuraavanlaisesti:

songlist
-ID
-artist
-title
-album
-trackno

categorylist
-ID
-songID //sama kuin songlist.ID
-categoryID
-sortID

category
-ID
-name
-parentID
-levelindex
-itemindex

Annan vielä tämänhetkisen koodini:

<?php
include ("kaplista.php");

  // Get the search variable from URL
  $artistit = @$_POST['artist'] ;

mysql_connect( "**********", "****", "*********" );
mysql_select_db( "samdb" )or die( "Ei pygee valitsee databeissii" );

// Haetaan categorylist

$cat = mysql_query( " SELECT *
                      FROM category"
                   ) or die('Error: ' . mysql_error());

$category = array();

while ($x = mysql_fetch_assoc($cat)) {
  $category[$x["ID"]] = $x;
}
mysql_free_result($cat);

// Haetaan songlist

$son = mysql_query( " SELECT
                       artist, album, title, trackno, ID,
                        (
                          SELECT
                            GROUP_CONCAT(DISTINCT categoryID ORDER BY categoryID SEPARATOR ',')
                          FROM
                            categorylist
                          WHERE
                            categorylist.songID = songlist.ID
                         )
                       AS 'categorylist'
                       FROM songlist
                       WHERE songlist.songtype LIKE 'S' AND songlist.status LIKE '0' AND songlist.artist LIKE '$artistit'
                       ORDER BY artist, album, trackno"
                   ) or die('Error: ' . mysql_error());

$songlist = array();

while ($y = mysql_fetch_assoc($son)) {
  $songlist[] = $y;
}
mysql_free_result($son);

$songs = array();
foreach ($songlist as $song) {
  // Puretaan kategorialista taulukoksi, jossa category.ID on avaimena
  $song["categorylist"] = array_flip(explode(",", $song["categorylist"]));
  // Merkataan puuttuviin kategorioihin false ja löytyineisiin true
  foreach ($category as $id => $c) {
    $song["categorylist"][$id] = isset($song["categorylist"][$id]);
  }
  $songs[$song["ID"]] = $song;
}
unset($songlist);

// Tulostellaan

echo "<h2>Haetut Kappaleet:</h2>";

// Otetaan kategorioiden määrä ja ID:t talteen
$cat_count = count($category);
$category_id_arr = array_keys($category);

echo "<table>\n";

// Tulostetaan otsikkorivi: artisti, albumi, kappale, kategoriat, ...
echo "<thead><tr><th>artisti</th><th>albumi</th><th>kappale</th>";
foreach ($category as $c) {
  echo "<th>{$c["name"]}</th>";
}
echo "</tr></thead>\n";

// Tulostetaan kappaleet:
echo "<tbody>\n";
$artist = $album = null;
foreach ($songs as $row) {
  // Tarvittaessa uusi artisti
  if ($artist != $row["artist"]) {
    $artist = $row["artist"];
    $album = null;
        // <td colspan='$cat_count'></td> vie tilaa kategoriasolujen verran.
    echo "<tr><td class='artist' colspan='3'>$artist</td><td colspan='$cat_count'></td></tr>";
  }
  // Tarvittaessa uusi levy
  if ($album != $row["album"]) {
    $album = $row["album"];
    echo "<tr><td></td><td class='album' colspan='2'>$album</td><td colspan='$cat_count'></td></tr>\n";
  }
  // Kappaleen tiedot
  echo "<tr><td></td><td></td><td class='song'>{$row["title"]}</td>";
  // Kappaleen kategorialaatikot
  foreach ($category_id_arr as $cat_id) {
    $checked = $row["categorylist"][$cat_id];
    if ($checked) $checked = " checked"; else $checked = "";
    echo "<td><input type='checkbox' name='check[{$row["ID"]}][$cat_id]' $checked></td>";
  }
  echo "</tr>\n";
}
echo "</tbody>\n";
echo "</table>\n";

?>
</table>
</body>
</html>

Toki osaan tehdä formin jolla lähetetään uutta tietoa tietokantaan, mutta en keksi miten pitäisi tämän kanssa lähteä liikkeelle. Joten joudun taas kerran pyytämään nöyrästi apua.

apua!?

PS. jos haluatte käydä vilkaisemassa miltä tulos näyttää. Alla linkki (toimii jostain syystä vain IE:llä tai ei ainakaa FF näytä listaa.)
http://www.stageradio.com/kaplista.php

Metabolix [07.05.2009 21:30:30]

#

Suosittelen validia HTML:ää ja validaattorin käyttöä. Datan listautumisessa on ongelmana, että koodistasi puuttuu =-merkki. Olisit voinut todeta tämän itse ihan HTML-koodia vilmaisemalla: <option value'3 Doors Down'>, <option value'AC/DC'> jne.

Enemmänkin on syytä hämmästellä, että jostain syystä tuo IE:llä kuitenkin toimii. O_o

Muistahan myös tulostaessasi käyttää htmlspecialchars-funktiota.

Itse ongelmaan: Olisi aika tyhmää päivittää sadan kappaleen tiedot, jos vain yhtä on muutettu. Toisaalta alkuun voit aivan hyvin tehdä päivityksen niinkin, ehdit kyllä miettiä sitä vielä monta yötä.

Nythän checkboxit on nimetty niin, että kun data lähetetään, saat niistä suoraan songID-categoryID-parit, jotka kantaan täytyisi saada.

Antti Laaksonen [07.05.2009 21:55:27]

#

Vaihtoehdot ovat siis ilmeisesti:

1. Taulusta categorylist poistetaan ensin kaikki rivit, joiden kappaleiden esittäjä on käsiteltävä esittäjä. Sitten tauluun lisätään rivejä sen mukaan, mitä valintaruutuja on valittu. Eli koko taulu categorylist käsiteltävän esittäjän osalta rakennetaan alusta asti uudestaan.

2. Taulusta categorylist poistetaan rivit, joita vastaavat valintaruudut oli valittu lomakkeen tulostushetkellä ja joiden valinnan käyttäjä poisti. Sitten tauluun lisätään rivit, joita vastaavia valintaruutuja ei ollut valittu lomakkeen tulostushetkellä ja jotka käyttäjä valitsi.

Vaihtoehto 1 on helpompi toteuttaa mutta voi rasittaa tietokantaa. Vaihtoehto 2 on vaikeampi toteuttaa mutta ei tee turhia muutoksia tietokantaan.

janijohannes [07.05.2009 22:14:07]

#

Jos ymmärsin kysymyksesi niin vastaan:

UPDATE table SET hitti = '$hitti', main = '$main', hidas = '$hidas' WHERE id = '$id'

Metabolix [07.05.2009 22:46:17]

#

janijohannes kirjoitti:

Jos ymmärsin kysymyksesi niin vastaan:

Et ymmärtänyt kysymystä. Eihän taulussa edes ole noin nimettyjä kenttiä, vaan kategoriat ja kappaleet on yhdistetty taululla, jossa on aina kappaleen ID ja kategorian ID. Joka kappaleella on tietenkin yhtä monta riviä kuin valittua kategoriaakin.

(Ei millään pahalla, mutta ehkä sinun pitäisi aina miettiä vähän pidempään, oletko ymmärtänyt kysymyksen ja tiedätkö asiasta tarpeeksi auttaaksesi. Olet viime aikoina monessa keskustelussa "neuvonut" aivan päin honkia, ja omat kysymyksesi ovat yleensä tätäkin helpompia.)

Antti Laaksonen kirjoitti:

Vaihtoehto 1 on helpompi toteuttaa mutta voi rasittaa tietokantaa. Vaihtoehto 2 on vaikeampi toteuttaa mutta ei tee turhia muutoksia tietokantaan.

Ei jälkimmäinenkään kovin vaikea ole. Sen voi toteuttaa suunnilleen näin (osittain pseudokoodia):

<?php
$new_cats_list = implode(",", array(/* kaikki uudet categoryID:t */));
$cat_id_arr = array(/* ne uudet categoryID:t, joita ei ennen ollut */);

$use_old = true;
foreach ($cat_id_arr as $c) {
  # jos vanhoja on ehkä jäljellä
  if ($use_old) {
    # yritetään päivittää yksi vanha (vääränlainen) uudeksi;
    # paluuarvona onnistuminen eli tieto, vieläkö niitä vääriä oli
    $use_old = mysql_query(
      "UPDATE categorylist
      SET categoryID = $c
      WHERE categoryID NOT IN ($new_cats_list) AND songID = $songID
      LIMIT 1"
    );
  }
  # jos vääriä ei ole (tai loppuivat; siksi ei käytetä elseä vaan on uusi if)
  if (!$use_old) {
    # lisätään uusi rivi
    mysql_query("INSERT categorylist SET songID = $songID, categoryID = $c");
  }
}
# poistetaan rivit, joilla on vielä väärä ID
mysql_query("DELETE FROM categorylist WHERE categoryID NOT IN ($new_cats_list)");
?>

stageradio [08.05.2009 10:07:07]

#

Teillä kyllä on aina vastaukset valmiina :D Taidan jopa ymmärtää periaatteen miten tuo toimii :)
Tällä hetkellä, kun listani listautuu artistin mukaan, joten ymmärtääkseni ainakin categorialistan poistamista pitää rajoittaa esimerkissäsi. Muutenhan kaikki muut artistit katoavat listalta. vai?
Mietin kanssa että mitähän ohjelma tykkää jos se on päällä ja hakee seuraavaa kappaletta soittolistalta samaan aikaan kun tätä päivitystä tehdään listalle. Tuskin mitään maata mullistavaa?

Ja tosiaan, yksi vaihtoehto olisi tietenkin tehdä vaikka jokaisen kappaleen perään nappula mistä kappaleen tiedot voisi päivittää.
Miinus puolena tulee vastaan tietenkin se, että joka kerralla kun nappia painaa, mennään tietysti toiselle sivulle ja kappaleet pitää listata uudelleen. Ellei sitten ole mahdollista jotenkin tehdä ikäänkuin tehdävä jonoa(muistia suoritettavista tehtävista) ja sitten kun kaikki tarvittava on muokattu suorittaa se. :) .. Onkohan edes järkevää / mahdollista...

Jos hyödyntäisi ajaxia niin ei kaiketi tarvitsisi sivua uudelleen laitailla? se on kuitenkin niin vierasta itselleni joten jätettäköön myöhemmäksi :)

Ja vielä viimoiseksi kysäisen että kun checkboxissa on ID:itten pari nii miten saan ne eroteltua päivittelykoodiin?

Tässä tuli varmasti monta tyhmää kysymystä, yrittäkää kestää :)

Grez [08.05.2009 10:28:02]

#

stageradio kirjoitti:

Mietin kanssa että mitähän ohjelma tykkää jos se on päällä ja hakee seuraavaa kappaletta soittolistalta samaan aikaan kun tätä päivitystä tehdään listalle. Tuskin mitään maata mullistavaa?

No sehän riippuu pikkuisen, mitä lukituksia ja kursoreita käytät. Käytännössä varmaan mullistavimmat mitä tuosta voi tapahtua on se, että rivi poistuu tulosjoukosta sen jälkeen kun olet tehnyt haun (dynaaminen palvelinpään kursori) tai sitten jos lukupuolella käytät lukitusta niin päivitys odottaa, tai aikarajojen ylittyessä epäonnistuu. Tuota poistumista hauan jälkeen tuskin edes mitenkään huomaisit rivi kerrallaan lukiessa.

Käytännössä jos käytät noita "normaalisti" niin ei tapahdu mitään ihmeellistä.

Metabolix [08.05.2009 10:35:14]

#

Checkboxit on nyt nimetty niin, että ne välittyvät PHP:lle taulukkoina. Lähetyksen tulos on tällä hetkellä sama kuin seuraavan koodin luoma taulukko:

<?php
$_POST["check"] = array(
  # kappaleen ID
  "24" => array(
    # rastittujen kategorioiden ID:t
    "3" => "on",
    "7" => "on",
    "9" => "on"
  )
  # kappaleen ID
  "25" => array(
    # rastittujen kategorioiden ID:t
    "3" => "on",
    "4" => "on"
  )
);

Näitä voit helposti käsitellä foreach-silmukalla (ks. PHP-opas) ja muilla taulukkofunktioilla (ks. PHP:n dokumentaatio, array_keys). Aiemmin valitut kappaleet voit hakea tietokannasta, tai jos mieluummin kuormitat nettiyhteyttä, niin voit toki tulostella ne checkboxien viereen hidden-inputteihin samalla tavalla nimettyinä (tietenkin nimeksi jotain muuta kuin "check").

stageradio [08.05.2009 11:42:56]

#

Suorastaan loistavaa. Olet siis jo tämänkin ottanut huomioon.
Enään minun täytyy siis opettaa itseäni käyttämään noita hyväkseni.
En voi muuta kuin kiittää.

Otan sitten taas suunnan tänne jos ilmenee ongelmia asian suhteen :)

Kiitos.

stageradio [11.05.2009 20:19:27]

#

Päädyin tuohon ensimmäiseen vaihtoehtoon. Tämä saa luvan kelvata vaikka rasittaahan tuo enemmän tietokantaa ja tekee turhia muutoksia, mutta tämän osasin tehdä "ihan" itse :D
Nyt voinkin sitten tyytyväisin mielin jatkaa radion kehittämistä muilta osin!

Suur-kiitos kaikille auttajille!


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta