Nyt olisi tarkoituksena siirtää omalla kotikoneella tehty MySQL-projekti oikealle serverille ja julkisesti nettiin.
Miten saisin kotikoneen phpmyadminista ulos selkeän SQL-koodin jonka voisin sitten syöttää julkisen palvelimen phpmyadminiin, jolloin tietokanta muodostuisi sinne oikeassa muodossa?
PhpMyAdmin-sivulla on export-toiminto (kai sulla on PhpMyAdmin?), jolla saat taulun ulos.
Oman koneen PhpMyAdminista vienti ja serverin PhpMyAdminista tuonti.
Siis talleta viennissä sql tiedosto (ruksaa talleta tiedostoon) väliaikaisesti johonkin kansioon josta sen sitten viet serverille.
kiitos. nuo auttoivat.
Riittääkö, että käytän tätä funktiota käyttäjän syöttämien tietojen karsintaan?
function siisti($str, $special=""){ $str = strip_tags($str); $str = htmlentities($str); $str = trim($str); $str = htmlspecialchars($str); $str = mysql_real_escape_string($str); $str = str_replace(array("ä", "ö"), array("ä", "ö"), $str); return $str; }
Eli tuo tehdään KAIKILLE syötöille, sekä GET- että POST-syötöille.
Ei tuossa ole järkeä. Käytä mysql_real_escape_string-funktiota kun talletat kantaan, ja htmlspecialchars-funktiota kun luet kannasta.
Mikä tuon viimeisen str_replacen tarkoitus on? &ä muunnettaisiin ä:ksi. Ja harvemmin kukaan alkaa tekstiään entiteeteillä kirjoittelemaan.
Mutta käytän samaa funktiota kaikkiin syöttöihin niin se on helpompi.
Tavoittelen vain sitä että tuo olisi mahdollisimman turvallinen
Lisäksi minulla on seuraava ongelma:
..tarpeeton koodi poistettu
Miten saisin niin että tämä ryhmittelisi samalle päivälle olevat varaukset yhden OPTGROUP alle ?
EDIT:Koodi olikin täysin toimiva, joten eipä mitää sittenkään !!
sellainen ongelma vielä
että
function ranstr($length) { $random= ""; srand((double)microtime()*1000000); //$char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //$char_list .= "abcdefghijklmnopqrstuvwxyz"; $char_list .= "1234567890"; // Add the special characters to $char_list if needed for($i = 0; $i < $length; $i++) { $random .= substr($char_list,(rand()%(strlen($char_list))), 1); } return $random; }
otin tuon koodin joltakin sivulta, ja muutin vähän.
Eli sen pitäisi luoda satunnainen numerosarja.
Jos määritän että pituus on 6 niin se saattaa joskus tehdä 5-numeroisia sarjoja. Mistä tämä johtuu?
Mikset käytä valmista funktiota?
Siksi että numerosarjan pituus pitää olla 6 merkkiä...
Eiköhän se numerosarja ole ihan oikein. Veikkaan, että muutat sen jossain vaiheessa luvuksi, jolloin etunollat häviävät.
Ykkösellä alkavan numerosarjankin saa helposti yhdellä arvonnalla: rand(100000, 999999)
. Nollalla alkava onnistuu, kun lisäät etunollat: sprintf("%06d", rand(0, 999999))
.
Kiitos vinkistä, käytän nyt rand() funktiota.
Miten voisin vielä varmistaa että numero ei ole vielä käytössä tietokannassa? Sen pitäisi siis olla niin että numero voi olla vain yhdellä rivillä per taulu.
Count laskee osumien määrän, joten jotain tyyliin
"SELECT COUNT(*) FROM taulu WHERE luku = ".$random
Jos palauttaa 0, niin lukua ei ole kannassa, muuten on. Näköjään MySQL:ssä on myös komento EXISTS, mutta en ole sitä koskaan käyttänyt.
Ensiksi täytyy tietenkin kysyä, miksi edes arvot tällaisen luvun. Eikö tietokannan automaattinen id:n generointi riitä, ja etkö voi edes muodostaa lukua jollain kaavalla id:stä?
Ei tietokanta generoi automaattisesti ID:tä
Tuo numeron on varausnumero ja se täytyy olal aina 6 merkkiä
varausnumeron perusteella voi sitten vaika poistaa varauksen ja muuta tällaista.
Miten saisin tuon Jaskan vinkin niin että jos se luku löytyy jo, niin arvotaan uusi. Tätä toistetaan niin kauan että löydetään käyttämätön luku
Jaska kirjoitti:
Count laskee osumien määrän, joten jotain tyyliin
"SELECT COUNT(*) FROM taulu WHERE luku = ".$randomJos palauttaa 0, niin lukua ei ole kannassa, muuten on. Näköjään MySQL:ssä on myös komento EXISTS, mutta en ole sitä koskaan käyttänyt.
Tuo nyt olis aivan hullua? Ai et lepois ensin vaikka 10 kyselyä kunnes sattumalta löytyis käyttämätön varausnumero ? :D
id = vn.
1 = 000001
2 = 000002
..
..
10 = 000010
100 = 000100
....
.....
9581 = 009581
Eix noi ole kaikki 6 pitusia, ja suht uniikkeja. ;)
Edit: Niin siis id == AUTO_INCREMENT, ja vn muodostuu siittä.
Olli kirjoitti:
Ei tietokanta generoi automaattisesti ID:tä
Se onkin sitten ihan oma syysi. :) Laita id-sarakkeelle AUTO_INCREMENT.
Minulla ei ole sellaista saraketta kuin id.
Ja varausnumero ei saa olla niin että se alkaisi nollalla, vaan pitää olla vaikeammin arvattavissa.
Pelkkä varausnumero ei riitä autentikointiin, joten sen arvattavuudella ei ole juurikaan merkitystä. Sinun pitää kysyä vähintään asiakkaan nimeä tai jotain muuta "salaista tietoa", ellet aio kirjautumispakkoa laittaa.
Varauksen poistossa kysytään sekä puhelinnumero että varausnumero.
No, kuitenkaan varausnumero ei voi olla tyyliä 0000001.
Eli taidan luottaa siihen että rand()
generoi riittävän satunnaisen numeron.
Olli kirjoitti:
Varauksen poistossa kysytään sekä puhelinnumero että varausnumero.
No, kuitenkaan varausnumero ei voi olla tyyliä 0000001.
Eli taidan luottaa siihen ettärand()
generoi riittävän satunnaisen numeron.
Mielestäni toi on vain niin typerää tapa luoda varausnumero. Eikä se tee siittä yhtään sen varmemmaksi, täytyy siihen kuitenkin joku muu autentikointi lisätä.
ALTER TABLE tilaukset AUTO_INCREMENT = 100000;
Eli aloita AI luvusta 100000, jos malli: 000001 ahistaa. Tai vaikka luvusta 398536 jos se tuntuu "varmemmalta".
Jaa. No taidan kuitenkin pysyä tuossa nykyisessä tavassa jota käytän.
Olli kirjoitti:
Jaa. No taidan kuitenkin pysyä tuossa nykyisessä tavassa jota käytän.
Miksi ihmeessä? :D
Haha, taitaa ottaa ihan luonnonpäälle, kun ei voi myöntää, että oma ratkaisu osoittautuikin täysin vääräksi.
Eikun menestystä vaan..
Ylleensä tietokannassa kannattaa olla jokin sarake, joka on varmasti yksilöllinen eikä lopu kesken.
Jos varausnumero "ei voi olla tyyliä 000001", joudut sillä randillakin melkoiseen pulaan, koska sekin tuottaa välissä mm. sellaisia lukuja kuin 123456, 101010 ja 111111.
Tässä on eräs mahdollinen funktio, joka muuttaa juoksevan id:n peruskäyttäjän näkökulmasta aivan satunnaisesti varauskoodiksi, jossa ei ole kahta samaa merkkiä ja joka ei ala nollasta. Koodien rajallisen määrän (ja käytettyjen kaavojen) vuoksi kierros alkaa aikanaan alusta, joten joihinkin hakuihin pitää silloin tietysti lisätä ehto, että haetaan vain avoimia varauksia, tai vanhat varaukset pitää välillä siivota tietokannasta. Käytännössä sykli on niin pitkä, että uusi kierros ei tule pienellä puljulla ikinä vastaan ja isommassakin edellinen saman koodin varaus on jo aikaa sitten käsitelty loppuun.
function koodiksi($id) { // Vaihtoehto A: 131072 eri koodia, vain numeroita. return luku_koodiksi(($id ^ 983016187) % 1048576 * 1019 % 131072, 6, "0123456789"); // Vaihtoehto B: 16777216 eri koodia, mukana kirjaimia return luku_koodiksi(($id ^ 983016187) % 16777216 * 127 % 513021600, 6, "0123456789ABCDEFHJKLMNPRSTUVWXY"); } function luku_koodiksi($luku, $pituus, $merkit) { $merkit = str_split($merkit); $koodi = array(); list($koodi[], $luku) = yksi(array_diff($merkit, array(0)), $luku); while (count($koodi) < $pituus) { list($koodi[], $luku) = yksi(array_diff($merkit, $koodi), $luku); } return implode($koodi); } function yksi($merkit, $i) { $j = $i % count($merkit); $i = ($i - $j) / count($merkit); $m = array_slice($merkit, $j, 1); return array($m[0], $i); }
Olli kirjoitti:
Jaa. No taidan kuitenkin pysyä tuossa nykyisessä tavassa jota käytän.
Kaikin mokomin, itsehän siitä kärsit (ja ehkä asiakkaasi sitten, kun homma ei toimi kunnolla).
Kiitos tuosta koodista.
Harkitsen, otanko sit äkäyttöön.
kirjoittaja kirjoitti:
Kaikin mokomin, itsehän siitä kärsit (ja ehkä asiakkaasi sitten, kun homma ei toimi kunnolla).
En usko että siitä tullee kärsimään, voin tarvittaessa poistaa sitten kannasta suoraan varauksia.
Ja tuskinpa päällekkäisiä numerosarjoja kuitenkana tulee tuolla rand funktiolla.
Olli kirjoitti:
Ja tuskinpa päällekkäisiä numerosarjoja kuitenkana tulee tuolla rand funktiolla.
Se että on mahdollisuus tulla päällekkäisyyksiä on merkki siitä että toteutustapa on väärä.
No tuota käyttäviä ei tule olemaan kovin montaa, joten en usko että päällekkäisiä tulee.
kirjoittaja kirjoitti:
Ylleensä tietokannassa kannattaa olla jokin sarake, joka on varmasti yksilöllinen eikä lopu kesken.
Ja tässä on vielä se ongelma että jos välistä poistetaan yksi varaus niin numerointi menee sekaisin.
Olli kirjoitti:
kirjoittaja kirjoitti:
Ylleensä tietokannassa kannattaa olla jokin sarake, joka on varmasti yksilöllinen eikä lopu kesken.
Ja tässä on vielä se ongelma että jos välistä poistetaan yksi varaus niin numerointi menee sekaisin.
Menee sekaisin vai juuri ei mene sekaisin?
Mielestäni numerointi juuri ei mene sekaisin, kun tilausnumerolla 72 tulee aina sama tilaus, oli sitä ennen poistettu 1 tai 60 tilausta.
Jos taas haluat tulostusvaiheessa ilmoittaa jonkun järjestysnumeron, niin käytä tähän jotain väliaikaista muuttujaa, jota kasvatat juoksevasti, mutta pidä se erillään tietokannan rivinumeroinnista.
Numerointi ei mene sekaisin, kun jokaiselle annetaan aina täysin käyttämätön numero – 1, 2, 3 ja niin edelleen. Aiemman poisto välistä ei vaikuta muiden numeroihin tai seuraavaan annettavaan numeroon mitenkään.
Tässä on vielä muutama konkreettinen luku siitä, miten todennäköisesti Ollin arvonta (rand(100000,999999)) on tietyssä vaiheessa tuottanut vähintään yhden törmäyksen.
N | p(törmäyksiä > 0) |
---|---|
100 | 0,55 % |
135 | 1,0 % |
305 | 5,0 % |
1000 | 42 % |
1117 | 50 % |
2000 | 89 % |
3000 | 99,3 % |
4000 | 99,99 % |
Ajoin pari käytännön testiä, jotka tukivat matematiikan pätevyyttä PHP:n rand-funktion tapauksessakin: tyypillinen törmäyskohta oli tuhannen arvonnan ympäristössä, pienimmillään osui jo 67:n jälkeen ja parissa tapauksessa vasta 3000:n jälkeen.
Metabolix kirjoitti:
Ylleensä tietokannassa kannattaa olla jokin sarake, joka on varmasti yksilöllinen eikä lopu kesken.
Jos varausnumero "ei voi olla tyyliä 000001", joudut sillä randillakin melkoiseen pulaan, koska sekin tuottaa välissä mm. sellaisia lukuja kuin 123456, 101010 ja 111111.
Tässä on eräs mahdollinen funktio, joka muuttaa juoksevan id:n peruskäyttäjän näkökulmasta aivan satunnaisesti varauskoodiksi, jossa ei ole kahta samaa merkkiä ja joka ei ala nollasta. Koodien rajallisen määrän (ja käytettyjen kaavojen) vuoksi kierros alkaa aikanaan alusta, joten joihinkin hakuihin pitää silloin tietysti lisätä ehto, että haetaan vain avoimia varauksia, tai vanhat varaukset pitää välillä siivota tietokannasta. Käytännössä sykli on niin pitkä, että uusi kierros ei tule pienellä puljulla ikinä vastaan ja isommassakin edellinen saman koodin varaus on jo aikaa sitten käsitelty loppuun.
.......
Jos nyt kuitenkin siirryn sitten tuohon, niin pitäisikö minun tehdä se niin että kun admin syöttää varattavia aikoja adminpaneelissa, niin numero tehtäisiin jo tuolloin vai missä vaiheessa se oikein tehtäisiin? Mietin että tuo sinun funktion tuottama arvo voisi saada oman sarakkeen tietokannasta, ja juokseva numero taas olisi omassa sarakkeessaan. Mutta miten poimin kyselyhetkellä seuraavan juoksevan numeron ?
Et poimi itse numeroa mitenkään, vaan asetat taulun sarakkeelle määreen AUTO_INCREMENT, jolloin numero tulee automaattisesti. (Tämä kuuluu ihan alkeisiin, oletko lukenut edes mitään SQL-opasta?)
CREATE TABLE taulu ( id INTEGER AUTO_INCREMENT PRIMARY KEY, tunnus CHAR(6), muujuttu TEXT ); INSERT INTO taulu (muujuttu) VALUES ("hei"); INSERT INTO taulu (muujuttu) VALUES ("moi"); INSERT INTO taulu (muujuttu) VALUES ("oho"); SELECT * FROM taulu;
+----+--------+----------+ | id | tunnus | muujuttu | +----+--------+----------+ | 1 | NULL | hei | | 2 | NULL | moi | | 3 | NULL | oho | +----+--------+----------+
Juuri lisätyn rivin id:n saa PHP:ssä funktiolla mysql_insert_id. Joudut tekemään lisäyksen jälkeen UPDATE-kyselyn, jolla asetat riville sen funktiolla generoidun 6-numeroisen tunnuksen tuohon NULL-arvon tilalle.
Hei,
olen kyllä lukenut oppaan, ja ymmärrän mitä auto_increment tarkoittaa.
Tarkotiin juuri tuota mitä viimeiseksi vastasit.
Mutta kun kokeilin luoda PMA:lla tuota saraketta sain virheilmoituksen:
SQL-lause: ALTER TABLE `varaukset` ADD `nro` INT NOT NULL AUTO_INCREMENT FIRST MySQL ilmoittaa: #1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
EDIT: Tässä vielä rakenne
Sarake Tyyppi Tyhjä Oletusarvo Linkitys sarakkeeseen: Kommentit MIME nro int(11) Ei varausnumero int(50) Ei aika int(50) Ei tyyppi int(50) Ei nimi text Ei puhelinnumero text Ei varattu text Ei
Ja nro lisäsin int:inä ilman AI koska ei suostunut sitä lisäämään .Myös muokkaamista kokeilin mutta siltikin antoi virheilmotuksen.
No luitko tuon virheilmoituksen? Auto_incrementin voi määrittää vain sarakkeelle, joka on taulun avain. Määritä siis kyseinen sarake primary keyksi.
Painoin primary key määritystä mutta se ei onnistunut. Eli mitä minun tulisi tehdä toisin?
Kokeilin tätä primary key nappia uudestaan ja sain tämän:
SQL-lause: ALTER TABLE `varaukset` ADD PRIMARY KEY ( `nro` ) MySQL ilmoittaa: #1062 - Duplicate entry '0' for key 'PRIMARY'
Jostain syystä kaikkien rivien nro arvo on nolla.
Pitäisiköhän arvot muuttaa tyhjäksi ?
Kokeilin tätä kyselyä:
UPDATE varaukset SET nro = ''
Kysely onnistui, mutta nro kenttien arvot olivat edelleen 0
En nyt jaksanut lukea koko ketjua, mutta tuntui että sinulla ei ole tuossa nro kentässä tällä hetkellä mitään järkevää.
Olisiko helpoin vain tuhota se pois ja tehdä uusi:
ALTER TABLE `varaukset` DROP `nro`; ALTER TABLE `varaukset` ADD COLUMN `nro` INT PRIMARY KEY AUTO_INCREMENT;
Kiitos tuosta se auttoi.
Mutta seuraava ongelma taas:
$kyselyt = "INSERT INTO varaukset(varausnumero, aika, varattu) VALUES "; $loppuu = "UPDATE varaukset"; for($i=0;$i<$maara;$i++){ $expi = explode(":", $exp[$i]); $nro = ranstr( TÄHÄN PITÄISI SAADA VIIMEISIN ID ); $tunti = $expi[0]*1; $minu = $expi[1]*1; $aika = mktime($tunti, $minu, "0", $kk, $paiva, $vuosi); $kyselyt .= "('".$nro."', '".$aika."', 'ei')"; $loppuu .= " SET nro = '".$nro."' WHERE aika = '".$aika."'"; $nr = $i+1; if($nr !== $maara){ $kyselyt .= ", "; } print $i; } print $kyselyt; mysql_query($kyselyt, $yhteys); mysql_query($loppuu, $yhteys);
Eli mihin kohtaan minun tulisi laittaa mysql_insert_id
funktio?
ranstr
funktio tekee saman kuin Metabolixin koodiksi
.
Tuohon koodiin ei mysql_insert_id-funktiota voi laittaa oikeastaan mihinkään, koska sitä pitää kutsua vasta mysql_queryn jälkeen. https://www.php.net/manual/en/function.mysql-insert-id.php
Yrität muutenkin tehdä asioita jotenkin uskomattoman monimutkaisesti.
Olettaen, että sarake nro sisältää juoksevan varausnumeron ja sarake varausnumero Metabolixin ranstr-funktiolla luodun koodin, voisit kokeilla jotain tällaista:
foreach ($exp as $i) { list ($tunti, $minu) = explode (":", $i); $aika = mktime ($tunti, $minu, 0, $kk, $paiva, $vuosi); mysql_query ("INSERT INTO varaukset (aika, varattu) VALUES ('$aika', 'ei')", $yhteys); $nro = mysql_insert_id ($yhteys); $varausnumero = ranstr ($nro); mysql_query ("UPDATE varaukset SET varausnumero = '$varausnumero' WHERE nro = '$nro'", $yhteys); }
En ole testannut ylläolevaa koodia, joten en anna takeita sen toiminnasta,
-tossu-
kiitos koodista, se rupesi toimimaan järjestelmässä hyvin !
En tiedä miten olin oikein tehnyt oman koodini, mutta jostai nsyystä se oli vain toiminut oikein.
Pyrin siihen että kaikki kyselyt olisi suoritettu kerrallaan mutta en tiedä oliko siinä järkeä.
mutta kiitos tuosta koodista ja kiitoksia muillekin avusta !
Hei,
miten voisin tehdä niin että saisin taulukon tyyliin
$taulu = array( 0 ==> 0, 1 ==> 0, 2 ==> 1, 3 ==> 4, .... 18 ==> 17, 19 ==> 20, .... );
Eli eri tuntien esiintymismäärä tulisi avaimen arvoksi. Vaikeaa on se että tunnit pitäisi jotenkin poimia aikaleimasta. Sen pitäisi varmaan olla jotain tyyliin
SELECT COUNT(*), aika FROM varaukset GROUP BY FROM_UNIXTIME(aika) LIKE '*-*-* *:**'
mutta loppuratkaisu puuttuu.
Eli aika-sarakkeessa on php:n time() muodossa oleva aika ja haluaisin niistä ylläesitetyn kaltaisen taulukon.
EDIT: Vielä toinen kysymys - eli miten saisin tuohon Metabolixin koodiin laskettua että kuinka monta varausnumeroa on vielä käyttämättä? Pitäisikö 131072:stä miinustaa nykyinen rivien määrä ?
Olli kirjoitti:
Hei,
miten voisin tehdä niin että saisin taulukon tyyliin
$taulu = array( 0 ==> 0, 1 ==> 0, 2 ==> 1, 3 ==> 4, .... 18 ==> 17, 19 ==> 20, .... );Eli eri tuntien esiintymismäärä tulisi avaimen arvoksi. Vaikeaa on se että tunnit pitäisi jotenkin poimia aikaleimasta. Sen pitäisi varmaan olla jotain tyyliin
SELECT COUNT(*), aika FROM varaukset GROUP BY FROM_UNIXTIME(aika) LIKE '*-*-* *:**'mutta loppuratkaisu puuttuu.
Eli aika-sarakkeessa on php:n time() muodossa oleva aika ja haluaisin niistä ylläesitetyn kaltaisen taulukon.
Antti Laaksonen antoi jo ratkaisun tällaiseen ongelmaan toisessa ketjussa.
lainaus:
miten saisin tuohon Metabolixin koodiin laskettua että kuinka monta varausnumeroa on vielä käyttämättä? Pitäisikö 131072:stä miinustaa nykyinen rivien määrä ?
Tietenkin suurin ID sen kertoo. Rivien määrä voi olla ihan mitä tahansa, siihen ei voi luottaa.
kirjoittaja kirjoitti:
Tietenkin suurin ID sen kertoo. Rivien määrä voi olla ihan mitä tahansa, siihen ei voi luottaa.
OK, pitää käyttää sitä sitten.
kirjoittaja kirjoitti:
Antti Laaksonen antoi jo ratkaisun tällaiseen ongelmaan toisessa ketjussa.
Mutta ajat ovat tuossa time() funktion arvossa eli miten saisin time funktion mukaan tuohon? Koska ne eivät ole suoraan kokonaislukuja...
Time() palauttaa juurikin kokonaislukuja. Otat HOUR()-funktiolla tunnin ja ryhmität sen mukaan. Sinä et tarvitse time()-funktiota mihinkään tuossa kyselyssä.
SELECT HOUR(FROM_UNIXTIME(time)) hour, COUNT(*) total FROM mytable GROUP BY hour
Ja unohda nuo LIKE-kikkailut ihan kokonaan.
Ahaa, kiitos tuosta kokeilen sitä myöhemmin!
Hei,
tuo koodi ei jostain syystä toiminut:
$kysely = "SELECT HOUR(FROM_UNIXTIME(aika)) hour, COUNT(*) total FROM varaukset GROUP BY hour"; $haku = mysql_query($kysely, $yhteys); $taulu = mysql_fetch_array($haku, MYSQL_ASSOC); print_r($taulu);
Se tulostaa
Array ( [hour] => 12 [total] => 1 )
Vaikka pitäisi tulostaa kuten halusin edellisessä viestissäni.
ja tietokannassa on nyt tunnit: 12, 14, 20, 17, 18 eli nuita kaikkia pitäisi olla ja arvona pitäisi olla lukumäärä.
Kokeile tätä:
kiitos rupesi toimimaan!
Aihe on jo aika vanha, joten et voi enää vastata siihen.