Update dat do databeze pomoci DUPLICATE KEY UPDATE

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
parti
Člen | 117
+
0
-

Ahoj nepomohl by mi nekdo se sestavenim dotazu pro update dat do DB. Mam zatim tohle.

while ($row = fgets($fileOpen)!== FALSE) { //fgets ziskava radky ze souboru
            // pri kazdem pruchodu bude v $row dalsi radek
            $cols = explode(',', $row);//delimeter
            //\Tracy\Debugger::barDump($folder);
            $a = isset($cols[0]) ? $cols[0] : '' ;
            $b = isset($cols[1]) ? $cols[1] : '' ; //isset vraci true nebo false, jestli volany index pole existuje.
            $c = isset($cols[2]) ? $cols[2] : '' ;
            //
            $sql-> mysql_query("INSERT into tabulka (a, b, c)  VALUES ('".$a."','".$b."','".$c."') ON DUPLICATE KEY UPDATE
                     mysql_query($sql) or die(mysql_error()))");
          // $row = $this->presenter->database->table('parking_user')->insert(array('parking_user_id'));

            //fclose($fileOpen);

         }

Dekuji moc za kazdu radu

CZechBoY
Člen | 3608
+
0
-

Se mi nějak zdá, že tohle nemá nic společnýho s Nette.
A pokud bych měl poradit tak stejně nevím co je tvým problémem.

parti
Člen | 117
+
0
-

Ano suhlas tohle neni nettovsky dotaz nevim jak ho prepsat.
Cil je update dat do db cez CSV. To uz mam ulozene. Ted resim prave ten dotaz.

CZechBoY
Člen | 3608
+
0
-

A co je teda cílem toho dotazu? Vidím, že se snažíš vložit data; když dojde k porušení nějakýho unikátního klíče tak se má provést update, ale nespecifikoval si co se má čím nahradit.

parti
Člen | 117
+
0
-

Cilem dotazu :
Dotaz by mel vlozit data do db. Napriklad $a – prezivka $b – jmeno $c – prijmeni. Jmeno a prijmeni muzu mit dva lidi stejny ale prezivku ne ta je unikatni.
Ve skratce mam csv ktere obsahuje naprikad prezivku, jmeno a prijmeni. A tyto udaje potrebuji dostat do db.Pridat nove a popripade stare updatovat.

nasel jsem si tohle a podle toho jsem i postupoval ale jak si rikal neni to nette dotaz do db.

http://dev.mysql.com/…plicate.html

Editoval parti (13. 1. 2017 9:31)

CZechBoY
Člen | 3608
+
0
-

Dobře, co se teda má stát, když by mělo dojít k vložení duplicitní přezdívky do databáze? Má se na konec přidat nějaký hash, číslo nebo třeba jen IDečko z auto incrementu na konec přezdívky?

parti
Člen | 117
+
0
-

Pokud by doslo ke vlozeni duplicitni prezivky tak to zahodi jako ze tam ten uzivatel uz je (existuje) jenom zkontroluje jestli se nezmenilo jeho jmeno nebo prijmeni.A jde dal.
A pokud by to byl novy uzivatel z prezivkou ktera tam uz uxistuje tak mu to vyhodi ze tato prizivka je uz obsazena.

Editoval parti (13. 1. 2017 9:53)

CZechBoY
Člen | 3608
+
0
-

To si myslim, že přes ON UPDATE KEY UDPATE nepůjde. Budeš muset zkontrolovat jestli už se daná kombinace v databázi vyskytuje, případně zavolat UPDATE nebo INSERT v závislosti na (ne)nalezené kombinaci.

parti
Člen | 117
+
+1
-

hm no bylo mi receno ze mam pouzit ON DUPLICATE KEY UPDATE tak jsem ted torchu zmateny.
Ten doatz zacinal Insertem a pak tam bylo ON DUPLICATE KEY UPDATE

$sql-> mysql_query("INSERT into tabulka (a, b, c)  VALUES ('".$a."','".$b."','".$c."') ON DUPLICATE KEY UPDATE
              //       mysql_query($sql) or die(mysql_error()))");

Nevim co ty nato??

Jeste se zeptam pokud to takto pustim tak mi to vyhodi
Undefined variable: sql
Kde ji ma definovat?
Nezlob se za tento typ dotazu ale ucim se dokumentace nette je v tom trochu zkromna :o( tak se ptam.

Editoval parti (13. 1. 2017 10:03)

CZechBoY
Člen | 3608
+
0
-

Jak dokumentace Nette? Však Nette nepoužíváš :D

Pro upřesnění: Chceš aby při vložení duplicitních dat se zkontrolovalo jméno+příjmení a zároveň chceš aby se to nezaložilo. tzn. pokud jsou údaje shodné tak je to ok, ale když se liší jméno/příjmení tak to nedovolit?

while ($row = fgets($fileOpen)!== FALSE) {
	$cols = explode(',', $row);

    $a = isset($cols[0]) ? $cols[0] : '' ;
    $b = isset($cols[1]) ? $cols[1] : '' ; //isset vraci true nebo false, jestli volany index pole existuje.
    $c = isset($cols[2]) ? $cols[2] : '' ;

	try {
		$this->databaseContext->table('table')->insert(array ( // zkusim vlozit radek
			'a' => $a,
			'b' => $b,
			'c' => $c,
		));
	} catch (\Nette\Database\UniqueConstraintViolationException $e) {
		$row = $this->databaseContext->table('table')->where('a', $a)->fetch(); // vytahnu existujici radek podle A
		if ($row->b === $b && $row->c === $c) {
			// ok
		} else
			// neco se zmenilo
		}
	}
}
parti
Člen | 117
+
0
-

No pokud budu nove udaje tak je tam vlozi.V zasade jde jenom o
1 – pridani novych uzivatelu.
2 – pokud by novy uzivatel ma prezivku ktera tam uz je tak ho to zahodi.(kontrola vkladanych uzivatelu podle prezivky)
3 – a starych uzivateloch jenom zkontroluje.Jestli nedoslo ke zmene jmena napriklad se slecna vda a zmeni se ji prijmeni tak se nahraje nove prijmeni.

Nette tady pouzivam ale to je jenom cast kodu co jsem poslal.

Editoval parti (13. 1. 2017 10:41)

CZechBoY
Člen | 3608
+
0
-
while ($row = fgets($fileOpen)!== FALSE) {
    $cols = explode(',', $row);

    $jmeno = isset($cols[0]) ? $cols[0] : '' ;
    $prijmeni = isset($cols[1]) ? $cols[1] : '' ;
    $prezdivka = isset($cols[2]) ? $cols[2] : '' ;

	if (trim($prezdivka) === '') {	// pokud je prazdna prezdivka
		continue;					// preskocit dalsi zpracovani
	}

    try {
        $this->databaseContext->table('uzivatel')->insert(array ( // zkusim vlozit radek
            'jmeno' 	=> $jmeno,
            'prijmeni' 	=> $prijmeni,
            'prezdivka' => $prezdivka,
        ));
    } catch (\Nette\Database\UniqueConstraintViolationException $e) {
        $row = $this->databaseContext->table('uzivatel')
					->select('jmeno')
					->select('prijmeni')
					->where('prezdivka', $prezdivka)
					->fetch(); // vytahnu existujici radek podle A
        if ($row->prijmeni === $prijmeni) {
			if ($row->jmeno === $jmeno) {
	            // ok
			} else {
				// zmenilo se jmeno
				$row->update(['prijmeni' => $prijmeni]);
			}
        } else
            // prijmeni je jine (a jmeno mozna taky)
        }
    }
}

Upozorním, že řešení předpokládá unikátní klíč na sloupci prezdivka.

Mysteria
Člen | 797
+
0
-

Nešlo by to použít takhle?

$this->database->query("INSERT INTO tabulka (a, b, c) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE a = VALUES(a), b = VALUES(b), c = VALUES(c);", $a, $b, $c);
parti
Člen | 117
+
0
-

dekuji moc jdu to hned vyzkouset.
A hlavne si to projit abych tomu i trochu porozumel.

CZechBoY
Člen | 3608
+
0
-

@Mysteria Nějak tam nevidím zakomponovanou tu část, kdy souhlasí první jméno, ale nesouhlasí příjmení.

Mysteria
Člen | 797
+
0
-

@CZechBoY Já to psal na tohle zadání:

Dotaz by mel vlozit data do db. Napriklad $a – prezivka $b – jmeno $c – prijmeni. Jmeno a prijmeni muzu mit > dva lidi stejny ale prezivku ne ta je unikatni.
Ve skratce mam csv ktere obsahuje naprikad prezivku, jmeno a prijmeni. A tyto udaje potrebuji dostat do > db.Pridat nove a popripade stare updatovat.

Pak by mu to fungovalo, když bude unikátní klíč na přezdívce, tak to vloží všechny nové a u existujících přezdívek to změní jména a příjmení na aktuální.

Záleží jak konkrétně myslí bod:

2 – pokud by novy uzivatel ma prezivku ktera tam uz je tak ho to zahodi.(kontrola vkladanych uzivatelu podle prezivky)

Pokud se v případě existující přezdívky má změnit jméno a příjmení na tu z CSV, tak moje fungovat bude. Pokud nechce v takovém případě dělat nic (tzn. nechat jméno a příjmení původní z databáze), tak bude potřeba použít to, co jsi navrhl ty.

parti
Člen | 117
+
0
-

Ahoj jenom pridavam svoje reseni na ukol.
Ukol byl nahravani a update dat pomoci csv.
Chci podekovat CZechBoY za pomoc a inspiraci.
Jsem jenom zacatecnik takze klidne mi to muzete zkritizovat.

$folder = dirname(__DIR__).'_DATA_'.'CSV/'. $year . '/' .$month. '/'.$date;
       FileSystem::createDir($folder);

       // save uploaded file to storage
       $file = $values['csv'];
       $file->move($folder. '/parking_'.substr(md5(rand()), 0, 8).'.'.'csv');
       $fileOpen = fopen($file,'r');

      $i = 1;
       while ($row = fgets($fileOpen, 1024)) {
           if ($i > 1) {
               $cols = explode(';', $row);
               $prezivka = Nette\Utils\Strings::trim(isset($cols[0])? $cols[0] : '');
               $jmeno = Nette\Utils\Strings::trim(isset($cols[1])? $cols[1] : '');
               $prijmeni = Nette\Utils\Strings::trim(isset($cols[2])? $cols[2] : '');

               $params = [$prezivka, $jmeno, $prijmeni,$prezivka, $jmeno, $prijmeni];
               $sql = 'INSERT INTO parking_user(prezivka,jmeno,prijmeni)
                   VAlUES (?,?,?)
                   ON DUPLICATE KEY UPDATE prezivka = ?, jmeno = ?, prijmeni = ?';
               $this->presenter->database->queryArgs($sql, $params);
           }
           $i++;
       }

Jenom by me ciste ze zvedavosti a teoreticky zaojimalo jestli ma nette nejake moznosti na konci uploudu vypsat pocet uspesnych nahrani napriklad „bylo nahrano 100 zaznamu z toho 5 neuspesnych“.
Je to len ciste teoreticka otazka.

CZechBoY
Člen | 3608
+
0
-

@parti Nikdy nepřistupuj k property presenteru! Ani pokud by to měl být BasePresenter.
V té tvé službě/komponentě použij dependency injection a předej si všechny závislosti (např. databázi) přes konstruktor. https://doc.nette.org/…dependencies

Ohledně vypsání nějaké hlášky – existuje flashMessage jak v presenteru tak i komponentě (každý si vypisuje ty svoje).
https://doc.nette.org/…n/components#…

parti
Člen | 117
+
0
-

OK dekuji za informace.
Jen by me jeste zaojimalo pokud bych chtel rozsirit exploed o vice oddelovacu jako je carka dvojetcka ma nette neco nato?
zkusil jem neco take

$delimiters = Array(";",",",":","|","-");

 $cols = explode($delimiters[0],$row);

ale nedela to co by to melo.

Co se tyka te db tak to je tady cele spatne napsane a suhlasim stebou.

Editoval parti (16. 1. 2017 9:53)

CZechBoY
Člen | 3608
+
0
-

Pokud parsuješ nějaký CSV tak bych doporučil spíš něco na práci s CSV. Třeba fgetcsv jako minimální základ – existují určitě i nějaké hezké knihovny, ale žádnou nepoužívám.
Takže tvým problémem bude zjistit jakej oddělovač se používá.

parti
Člen | 117
+
0
-

Dekuji moc za typ.

parti
Člen | 117
+
0
-

Ahoj tak zase zpatky. Nevite kde mam chybu? Respektive pokud nahravam stejny csv se stejnym obsahom dat tak to projde a vlozit to do db stejne data. Pokud je v csv nejaka zmena tak to pracuje spravne ale kdyz tam neni tak to nahraje znovu vsechno. Takze se muze stat ze to uzivatel nahraje dva krat.SPATNE

$folder = dirname(__DIR__).'_DATA_'.'CSV/'. $year . '/' .$month. '/'.$date;
       FileSystem::createDir($folder);

       // save uploaded file to storage
       $file = $values['csv'];
       $file->move($folder. '/parking_'.substr(md5(rand()), 0, 8).'.'.'csv');
       $fileOpen = fopen($file,'r');

      $i = 1;
       while ($row = fgets($fileOpen, 1024)) {
           if ($i > 1) {
               $cols = explode(';', $row);
               $prezivka = Nette\Utils\Strings::trim(isset($cols[0])? $cols[0] : '');
               $jmeno = Nette\Utils\Strings::trim(isset($cols[1])? $cols[1] : '');
               $prijmeni = Nette\Utils\Strings::trim(isset($cols[2])? $cols[2] : '');

               $params = [$prezivka, $jmeno, $prijmeni,$prezivka, $jmeno, $prijmeni];
               $sql = 'INSERT INTO parking_user(prezivka,jmeno,prijmeni)
                   VAlUES (?,?,?)
                   ON DUPLICATE KEY UPDATE prezivka = ?, jmeno = ?, prijmeni = ?';
               $this->presenter->database->queryArgs($sql, $params);
           }
           $i++;
       }

Nevite co mam spatne??

CZechBoY
Člen | 3608
+
0
-

Nechybi ti tam unikatni klic na prezdivce?

parti
Člen | 117
+
0
-

jj mas pravdu uz jsem to nastavil.
DEKUJI Kloubok dole pred vasima znalostmi.

Editoval parti (16. 1. 2017 14:02)

parti
Člen | 117
+
0
-

Nevite nahodou o nejake nahrade multiexplode????
Potrebval bych aby explode umel vic ne jenom strednik. Vyzkousel jsem taky i fgetcsv ale ten taky neumi vic delimetru.

Dekuji za info

Editoval parti (16. 1. 2017 15:15)

CZechBoY
Člen | 3608
+
0
-

A jak si to predstavujes? Ze v jednom radku muzes oddelovat treba 4 oddelovacema? Nebo v celem souboru jen 1?
Jde ti o to urceni oddelovace jak jsem psal nahore?

parti
Člen | 117
+
0
-

Jde o to ze v csv muze byt pouzit misto stredniku carka a v tom pripade kdzy tam bude carka tak to neoddeli a vse hodi v DB do jednoho sloupce.
priklad:

mrkva;petrzel;brambora – OK vlozi do db spravne a rozdeli do slopcu.
mrkva;petrzel;brambora
mrkva,petrzel,brambora -vlozi spatne vse do jednoho sloupce

$cols = explode(';', $row);

zkousel jsem musltiexplode, dale to dat do pole atd.. ale nic

Editoval parti (16. 1. 2017 15:32)

CZechBoY
Člen | 3608
+
0
-

Takze ktera varianta to je? Kazdy radek ma jiny oddelovac, nebo kazdy soubor ma jiny oddelovac?

parti
Člen | 117
+
0
-

no musim vyresit obe strednik i carka.
Co kdzy tam bude carka i strednik v jednom csv. Nebo jeden uzivatel tam bude chtit dat csv ze strednikami a dalsi s carkami.
Proto ten delimeter s vice moznostmy.

Editoval parti (16. 1. 2017 15:51)

CZechBoY
Člen | 3608
+
0
-

Odkud beres to csv? Nejde pri zadavani vynutit nejaky normalni format?
S timhle by te treba Excel poslal do pryc… nebo zobrazil spatne vysloupcovany :-)

parti
Člen | 117
+
0
-

No je tezke ohlidat kazdeho kdo to bude vkladat csv. Nevim jak to bude tvurce csv exportovat. Muze to byt ze strednikem nebo carkou.
Tak nevim jak to osetrit.
Puvodne jsem myslel ze delimeter toho umi vice.

Editoval parti (16. 1. 2017 15:59)

h4kuna
Backer | 740
+
0
-

SplFileObject má možnost čtení jako csv

$splFile = new \SplFileObject($file);
$splFile->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);

foreach($splFile as $row) {
	dump($row);
}
h4kuna
Backer | 740
+
0
-

Tak to napiš k nahrávacímu inputu jaký jsou podmínky. Že oddělovač je čárka uživatele když už exportují do csv tak na toto se jich program zeptá.

parti
Člen | 117
+
0
-

ok tak reseni na vice znamku pro delimetr

$cols = preg_split( "/;|,/" , $row);

dekuji za info ohledne SplFileObject.

h4kuna
Backer | 740
+
0
-

Na ten split se nemůžeš spolehnout

"Bar,","foo;"
CZechBoY
Člen | 3608
+
0
-

@h4kuna to ani na ten explode ;-)

h4kuna
Backer | 740
+
0
-

@CZechBoY já vím, nikdy jsem nebyl pro variantu s explode. Nabídl jsem SplFileObject. Musí si s tím pohrát.

parti
Člen | 117
+
0
-

Ok diky kluci to me nenapadlo s tou carkou uvnitř „Bar,“,„foo;“ podivam se na tu variantu SplFileObject.
Jeste to tak nepoznam tak jsem rad za kazde nasmerovaní.
@h4kuna nebudes nahodou 28.1. na te sobote s nette?