Autor Zpráva
candiess
Profil
Dobrý, chci se zeptat..

Mam php aplikaci, která mi zapisuje data do DB
<?php
$cislo1 = rand(5,100);
$cislo2 = rand(100,500);
$cislo3 = rand(500,8000);
$cislo4 = rand(800,8000);
$cislo = $cislo1.$cislo2.$cislo3.$cislo4;

$dotaz = "INSERT INTO groups(ID,text) VALUES ('$cislo','$title')";

$query = setQuery($dotaz) or print(msg("w","Query - ".mysql_error()));
?>


a mysql mi vyhodí ,,Duplicate entry '2147483647' for key 'PRIMARY'"

Ví si někdo rady prosím?
motik
Profil
candiess:
slovník určitě pomůže

[EDIT]podle mě je blbost dávat náhodné číslo - není lepší použít AUTO_INCREMENT?
candiess
Profil
motik:
Samozřejmě sem si to přeložil ale at dělám co dělám tak mi to prostě nejde, ok? Psal sem si o radu ;)
motik
Profil
candiess:
přečti si např. přehled datových typů

EDIT: řešení - předělej to na ten AUTO_INCREMENT (předejdeš tím dalším problémů)
candiess
Profil
motik:
OK dík, budu muset zredukovat to číslo :)


Problém vyřešen, změněný datový typ.
Joker
Profil
candiess:
No to je prosté:
Vygenerují se ta 4 náhodná čísla a pak se spojí. Výsledkem bude číslo od 5100500800 do 10050080008000.
Poté se to převede na řetězec.
A nakonec se to uloží do databáze, nejspíš do sloupce typu (signed) INT, který je zároveň primární klíč.
Databáze se pokusí řetězec převést zpět na číslo, ale protože nejvyšší možná hodnota signed INTu je 2147483647 a ten řetězec vždycky reprezentuje větší číslo, bude výsledkem pokaždé hodnota 2147483647.
No a když ten sloupec je zároveň primární klíč, projde jen první zápis a druhý a další nahlásí to „duplicate entry“

Je to takový „generátor nenáhodného čísla“ :-)

Jinak se ale přiznám, že nechápu smysl ani jednoho z těch kroků. Vlastně celý ten kód je od začátku do konce tak chybný, až je fascinující.
candiess
Profil
Joker:
Já vím já vím..zjednodušil jsem to tady, kostra toho prgramu je daleko složitější.

Jde tu o to aby se mi generovala uplně náhodná velká čísla, mohl bych to udělat přes AUTO_INCREMENT ale poté by někdo zadal www.example.cz/groups/1 a prostě bylo by to špatné..
motik
Profil
candiess:
mohl bych to udělat přes AUTO_INCREMENT ale poté by někdo zadal www.example.cz/groups/1 a prostě bylo by to špatné..
no šak si ho můžeš nastavit na nějaký vyšší číslo

[EDIT]candiess:
Problém vyřešen, ...
problém odložen ;-)
candiess
Profil
motik:
Dobrá dobrá :D
Upravuji sloupec, vidím políčko na zaškrnutí hodnoty AUTO_INCREMENT, kde mám ovšem zapsat to číslo od kterého se to bude přičítat?
okolojdouci
Profil *
candiess:
Jestli jde o zamaskování dalších ID, udělej to třeba vygenerováním náhodného řetězce (s ověřením, jestli už v tabulce není). Tvůj postup znamená jistotu, že budeš mít problém. Jen nevíš kdy.
Inspiruj se:
function rndstring() {
  $delka = 6;
  $existuje = 1;
  $chars = "abcdefghijklmnopqrstuvwxyz0123456789";

  while ($existuje==1) {
    $ret = "";
    while (strlen($ret) < $delka) {
      $ret .= $chars[mt_rand(0,strlen($chars))];
    }
    $existuje = mysql_result(mysql_query("SELECT COUNT(*) FROM vouchery WHERE vouchername = '".$ret."'"), 0);
  }

  return $ret;
}
motik
Profil
okolojdouci:
Jestli jde o zamaskování dalších ID,
podle mě mu jde spíš o to, že to vypadá divně..

candiess:
Dobrá dobrá :D
Upravuji sloupec, vidím políčko na zaškrnutí hodnoty AUTO_INCREMENT, kde mám ovšem zapsat to číslo od kterého se to bude přičítat?
nenutím tě do toho, jen se ti snažím pomoc předejít dalším chybám..
to číslo nastavíš sql dotazem - zkus google, ten ti pomůže..

[EDIT] máš to i v diskusi pod tím článkem datové... (ALTER TABLE tabulka AUTO_INCREMENT = cislo)
Joker
Profil
motik:
no šak si ho můžeš nastavit na nějaký vyšší číslo
To nepomůže, předpokládám candiessovi jde o to, aby ty hodnoty nešly za sebou. Tj. například když mám skript.php?id=5000, aby předchozí hodnota nebyla skript.php?id=4999.

candiess:
Každopádně pro vkládání čísla do číselného sloupce přes řetězec žádná omluva není.

A myslím, že popsaný cíl by šel zajistit i bez generování ohromných náhodných čísel.
Stačilo by například identifikátor záznamu složit ze sekvenčního čísla od 100 dál a třímístného náhodného čísla. Takže ID po sobě jdoucích záznamů by byla například:
100239, 101820, 102391, 103715, atd.

Každé ID je vždy unikátní (protože první trojčíslí je unikátní), zároveň z ID jednoho záznamu není jednoduše odhalitelné ID jiného záznamu (algoritmus není na první pohled patrný, kdo by ho znal věděl by, že třeba záznamu 203907, předchází záznam 202xxx, ale pořád je 899 možností - myslím, že pro „běžné použití“ to je dostatečné) a přitom na to není potřeba BIGINT.
candiess
Profil
okolojdouci:
Děkuji za script ovšem jde mi opravdu o to že ta jednička vypadá blbě :)

motik:
Oukéj díky moc, vemu si z toho ponaučení :)
Joker
Profil
okolojdouci:
Generovat náhodné ID a testovat jestli už tam je není ideální řešení:
- Pokud je podstatná část kombinací už obsazena, degraduje výkon aplikace; Například při vyčerpání 80% možných kombinací, bude ten cyklus pro většinu nových záznamů muset proběhnout nejméně 3x. Při vyčerpání 99% kombinací ten cyklus většinou proběhne nejméně 68x.
- Jsou-li všechny kombinace vyčerpané, pokus o přidělení nového ID vede do nekonečného cyklu.
- Předchozí odrážky vedou k nutnosti vyhradit pro IDčka daleko víc kombinací než kolik se reálně může přidělit, což se často jednak těžko předpovídá a jednak je to plýtvání místem.
- Navíc zpomalení je už to, že se vůbec musí ověřovat, jestli dané IDčko v databázi už není.

Čili podle mého názoru u hodnoty která má být unikátní je lepší zajistit její unikátnost algoritmem jejího výběru, než generovat náhodné číslo.
okolojdouci
Profil *
Joker:
Ve všech bodech obžaloby máš pravdu. Ten můj kód vycházel z konkrétního zadání, kde jsem měl generovat desetiznakový kód - z důvodů jiných než mých interních - takže tím padá argument o délce a při 36^10 kombinacích a při potřebě řádově stovek kódů ročně nejspíš i ty ostatní. Ale uznávám, že to použití je potřeba zvážit.

Ještě vidím, že 6. řádek bych dneska určitě napsal radši takto:
while ($existuje>0) {

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0