Phoca Cart

Odpověď od H13
20. říj 2016 16:20 #128868

Jinak pokud by bylo ID před dvojtečkou, tak nějaký spec. znak není přece třeba řešit. Prostě by se za ID považovala všechny číslice 0-9 před první dvojtečkou.


Souhlas, formát: 1:Jméno bude asi nejlepší, jak píšeš, s kontrolou INT před dvojtečkou. Jméno bez čísla, to by byl masakr pro databázi, hledat v každém řádku jméno kategorie,navíc v utf-8. Ono s těma ID to bude samozřejmě komplikovanější, např. ID produktu, příklad import.

Importuje se řádek, který obsahuje ID 23, ale takový už existuje v databázi, co teď:

- vymazat ten v databázi
- nemazat ho
- pouze updatovat (v podstatě znamená vymazat ten v databázi)
- nebo ignorovat ID a posunout produkt na další ID (protože ID je autoincrement)

Tady se asi parametru "Přepsat existující produkt při importu" (ANO/NE) nevyhnu. No a samozřejmě pokud taková možnost bude, pak se zase dostáváme k tomu, že se nebude moct použít následující varianta č.1:

Možnosti při importu dat:

varianta č.1) Při importu se smažou stávající data a nahradí se pomocí INSERT (hodně rychlá varianta, nenáročná na SQL dotaz, ale není to update)

varianta č.2) Při importu se kontrolují stávající data a nahrazují se pomocí INSERT ... ON DUPLICATE KEY UPDATE (vlož, pokud existuje ID, pouze udělaj update) - Problém ON DUPLICATE KEY UPDATE je, že se nedokáže provést v jednom SQL dotazu pro všechny vložné řádky a musí se opakovat ve foreach :-) - což může být u více položek hodně problematický :-(

A to nemluvím o kontrole vztahu ID vs. Jméno:

- ID neexistuje OK
- ID existuje - přepsat
- ID existuje ale jméno ve spojitosti s ID neexistuje - v databáz je 23:Jablko, a teď uživatel importuje 23:Hruška - co teď - je to nový produkt a prostě dáme jiné ID 26:Hruška, nebo uživatel změnil 23 z Jablka na Hrušku a není to nové ID, jen název je jiný ??? Tady už si taky nemusíme vystačit jen SQL, ale budeme muset kontrolovat i pomocí PHP a načítání jednotlivých řádků - což by taky mohlo databázi totálně zatížit :-(

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
20. říj 2016 19:31 #128870
Identifikaci produktu bych při importu spíš než na ID pověsil na SKU. Opět ID nikomu nic moc neřekne, SKU je poměrně jasný identifikátor, každý ví co si má pod ním představit. No a pokud SKU existuje, tak hodnoty přepsat, protože když už bude mít někdo duplicitní SKU, tak je to jeho boj. Takže pokud pod SKU 123 místo Jabka nahrává Hrušku, tak přepsat.

Popř. by bylo hezký mít možnost importovat dle EAN.

Stávající data bych při importu nemazal, tím by se zase zavřela cesta pro nějaký zjednodušený import - typicky pouze aktualizace cen - tedy jednou za čas nahraji komplet sortiment s popisy apod. ale třeba každý týden přeceňuji a chci nahrát jen nové ceny.

S ON DUPLICATE KEY je ještě potíž v tom, že je to jen MySQL. Do budoucna tedy problémy s kompatibilitou s jiným SQL serverem (nevím tedy jestli s tím vůbec počítáš).

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
20. říj 2016 23:25 #128872
Problém je, že jediný ID je skutečně identifikátor. U produktů jsou sloupce EAN, SKU, ISBN a podobně a teoreticky by se dal přidat parametr pro výběr klíčového sloupce. Např. vyberu EAN a pokud bude EAN stejné, pak řádek jen updatuju. Tam by ale zase byl problém s S ON DUPLICATE KEY, který potřebuje mít daný sloupec jako klíč, aby se podle něj řídil - a dělat dynamicky změny ve struktuře databáze, to asi není vhodné řešení.

Vše optimalizuji pro MySQL / MariaDB, za cca 9 let jsem měl snad jen jednu otázku na podporu MSSQL, takže ostatní databáze jsem zatím neměl důvod řešit

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
20. říj 2016 23:56 #128873

H13 napsal: Problém je, že jediný ID je skutečně identifikátor.

Systémově třeba ano (i když u toho SKU by možná Unique index stál za zvážení), ale v praxi je obvykle SKU nebo EAN jedinečný. Pokud se SKU potká od dvou dodavatelů je naprosto běžným standartem, že si jej firmy upraví předponou tak aby jedinečné u nich v systému bylo.

EAN je také v drtivé většině případů jedinečný, i když u některého sortimentu se "točí" - zjistil jsem to např. u levných DVD, tam jeden EAN točili na několik různých titulů.

Ale je fakt, že jsem zapomněl že v MySQL je potřeba ten Unique index. Bez něj by to muselo být nejdřív dohledání a pak insert nebo update.

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
21. říj 2016 12:05 #128875
Teoreticky se dá dát klíč více sloupcům: primary key = id, key = ean, sku, ... Při "aplikaci" ON DUPLICATE KEY, když dostane řádek se stejným EAN a jiným SKU, prostě updatuje ten řádek s EAN, pokud se stejným SKU, pak zase updatuje řádek se SKU, pokud budou obě odlišné, pak vloží nový řádek.

Já si to teď testuju:
INSERT INTO products (title, ean, isbn, sku) VALUES ('xxx', 'yyy', 'zzz', 'aaa')
ON DUPLICATE KEY UPDATE title = VALUES (title), ean = VALUES (ean), isbn = VALUES (isbn), sku = VALUES(sku);

S tím, že se musí vypsat všechny sloupce pro duplicate (title= VALUES(title)). Otázkou je zda to nebude moc náročné (paměť, čas) :idea:

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
21. říj 2016 12:42 #128876
No ale aby fungovalo to ON DUPLICATE KEY tak musí být ty indexy Unique ne? To by znamenalo zásah do struktury databáze, trochu změna filozofie těchto sloupců. Ale pak by to fungovalo, to je pravda, jen nevím, jestli, když to pojede podle všech sloupců, by pak nedocházelo ke zmatení co se vlastně aktualizovalo a proč.

ON DUPLICATE KEY používám v jednom projektu v podstatě přesně k tomuto (i když tam je to pravda dle primárního klíče), a spuštění 1000 update je pod sekundu na běžném hostingu, nemám to přesně změřené, ale je to dost rychlé.

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
21. říj 2016 15:03 #128877
Ano, unikátní klíče:

ALTER TABLE `products`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `eanx` (`ean`),
ADD UNIQUE KEY `isbnx` (`isbn`);

Při ukládání produktů v Joomle! by problém být neměl, tam to je tak, že pokud existuje ID, pak je to standardní UPDATE, a pokud neexistuje, je to INSERT - vždy se jedná o jeden řádek. Při zobrazování (SELECT) by snad taky neměl být problém.

Konrétně v Phoca Cart jsou tyto možné klíčové sloupce:

`sku` varchar(255) NOT NULL DEFAULT '',
`upc` varchar(15) NOT NULL DEFAULT '',
`ean` varchar(15) NOT NULL DEFAULT '',
`jan` varchar(15) NOT NULL DEFAULT '',
`isbn` varchar(15) NOT NULL DEFAULT '',
`mpn` varchar(255) NOT NULL DEFAULT '',

Aby jsme to nepřeháněli, můžeme vybrat např. SKU a EAN. Jenže co to Japonci (JAN), univerzálové (UPC), výrobci (MPN) a nebo dokonce knihovníci (ISBN)? :-)

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
21. říj 2016 15:17 #128878
V Joomle by asi problém nebyl, ale nevím jak je to s reálnou jedinečností takových kódů jako ISBN nebo MPN - u toho MPN bych o tom pochyboval, tam se to podle mně může potkat u dvou různých výrobců. ISBN jsem se tuším také s někým bavil, kdo mi tvrdil, že ty kódy se opakují, např. na různá vydání stejné knihy (ale s jiným obalem, cenou, někdy třeba i s revidovaným obsahem - tedy jiné položky).

Jestli by nebylo rozumnější raději obětovat výkon při importu a dělat jej dvěma dotazy, než být příliš restriktivní v databázi.

Třeba Firebird to má v SQL vyřešené daleko lépe, tam se u UPDATE OR INSERT určuje podle čeho se má řádek dohledat, MySQL v tom není moc univerzální :(

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
21. říj 2016 15:38 #128879

Jestli by nebylo rozumnější raději obětovat výkon při importu a dělat jej dvěma dotazy, než být příliš restriktivní v databázi.


Myslíš něco jako:

$result = mysql_query("update products set title='test' where sku='111';");
if (mysql_affected_rows()==0) {
$result = mysql_query("insert into products (title, sku) values ('test','111');");
}


s tím, že where může být variabilní (nastavitelné přes parametr, tedy podle toho co uživatel používá) :idea:

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
21. říj 2016 16:50 #128882
No vida, to mě ani nenapadlo mysql_affected_rows - ale to by to možná vyřešilo ještě elegantněji.
Já myslel klasický select a pak buď insert nebo update, ale pravda je, že takhle by se v ideálním případě ušetřila polovina dotazů.

Takhle to vypadá velmi slibně, variabilní where - ať si každý rozhodne jestli je pro něj důležitý SKU nebo EAN (popř. jiný kód), a jedinečnost ať si hlídá sám... Teoreticky by šlo ještě kontrolu na jedinečnost provádět jen v PHP - v JTable, také podle nastavení. Pak by nemusel být unique index, a jen ukládání by se zpomalilo o dotaz navíc.

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
23. říj 2016 14:07 - 23. říj 2016 16:56 #128895
No, dívám se na různý články, jak efektivně importovat data z CSV a vůbec nikdo nikde nepočíta s updatem. Prostě při importu se vymaže kompletně tabulka "truncate table" a pak se v php foreachem naskládá INSERT a ten se vloží.

Neřeší se UPDATE, jeden skript by měl zvládnout tisíce řádku, takže se neřeší ani stránkování.

Pokud bychom řešili i update, musí to mít i stránkování, tedy např. přes AJAX posílat posílat určitý počet řádků. Jenže tam zase může být v tom, že při každý ajax instanci se otevírá soubor, což je taky na nic :-(


Jinak těch možností jak importovat CSV je opravdu hodně, dokonce se to dá zvládnout i s načtením souboru jen v mysql (LOAD DATA INFILE)

A tohle je hodně zajímavý (přes dočasnou tabulku i možnost updatu):
CREATE TEMPORARY TABLE your_temp_table LIKE your_table;

LOAD DATA INFILE '/tmp/your_file.csv'
INTO TABLE your_temp_table
FIELDS TERMINATED BY ','
(id, product, sku, department, quantity); 

UPDATE your_table
INNER JOIN your_temp_table on your_temp_table.id = your_table.id
SET your_table.quantity = your_temp_table.quantity;

DROP TEMPORARY TABLE your_temp_table;

stackoverflow.com/questions/10253605/imp...-one-column-in-table

EDIT: zajímavý to je, ale bohužel kombinace updatu a různých sloupců, podle kterých se dá updatovat s LOAD DATA INFILE asi nepůjde, protože ta funkce nezná WHERE:
CREATE TEMPORARY TABLE products_temp LIKE products;

LOAD DATA INFILE 'test.csv'
INTO TABLE products_temp
FIELDS TERMINATED BY ','
(id, product_id, title, ean, isbn, sku); 

INSERT INTO products
SELECT product_id, title, ean, isbn, sku FROM products_temp
ON DUPLICATE KEY UPDATE product_id = VALUES(product_id), title = VALUES(title), ean = VALUES(ean), isbn = VALUES(isbn), sku = VALUES(sku);

DROP TEMPORARY TABLE products_temp;

Zvládne updatovat pomocí on duplicate key update ale už nezvládne updatovat podle zvoleného sloupce

Takže asi nezbývá nic jinýho, než PHP, načtení celýho CSV. a zkusit to smyčkou projet vše naráz.

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
23. říj 2016 21:55 #128896
No TRUNCATE a INSERT si moc nedokážu představit. Soubor by musel vždy obsahovat kompletní informace, včetně ID, ale i třeba dalších průběžně kalkulovaných sloupců. Teoreticky je to samozřejmě dobrá a rychlá věc, prakticky podle mně dost nepoužitelné.

U připojování externích souborů je zas potřeba brát ohled na to, co je reálně možné na běžném hostingu. NEznám do podrobna tuhle funkci, ale obávám se, že na normálním hostingu to asi ani nepůjde použít.

Nejrozumnější mi přijde opravdu zkusit to PHP, popř. pak otestovat výkonost (ale nebál bych se jí), případně fajnšmekrovsky doplnit AJAX. Pokud to bude CSV tak opětovné otevření souboru nebude nijak zvlášť velká zátěž (při čtení po řádkách, ne komplet načtení do paměti). Ono staré dobré CSV má ještě pořád hodně výhod oproti moderním XML, JSON a jiným formátům :)

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od H13
24. říj 2016 01:03 #128897
No, ono to nakonec PHP bude muset být a vše po jednom řádku - neuvědomil jsem si, že hodně sloupců (kategorie, atributy, specifikace) jsou propojeny přes referenční tabulky. Takže jak u importu tak exportu se nebude pracovat jen s jednou tabulkou ale více tabulkami najednou.

Phoca Gallery - http://www.phoca.cz/phocagallery - obrázková galerie (Joomla!)
Phoca Guestbook - http://www.phoca.cz/phocaguestbook - kniha návštěv (Joomla!)
Phoca Download - http://www.phoca.cz/phocadownload - stahování souborů (Joomla!)
Phoca Cart - http://www.phoca.cz/phocacart - e-shop,...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od HonzaKr
24. říj 2016 09:52 #128899
Omlouvám se, že Vám do toho zasahuji. Já bych při importu CSV z opatrnosti použl dočasnou tabulku do které bych všechno nasypal (nový i update) a následně zpracoval. V dávné dřevní době jsem řešil také import CSV a použíl jsem dokonce dvě dočasné tabulky. Do jedné jsem nasypal import a druhou jsem použil jako zálohu pro opravované záznamy. V případě chyby nebyl problém se vrátit k původním datům. Je pravda, že se jednalo o Pascal a datbáze byla Paradox, ale základní princip je stejný.

:: bývalý člen Joomlaportalu ::

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.

Odpověď od Cony
24. říj 2016 10:26 #128902
No ono MySQL bez transakcí se v tomto ohledu moc od Paradoxu neliší :) A Pascal bude ve zpracování CSV určitě výkonější než PHP.

Je pravda, že se tato technika taky používá, obvykle hlavně z důvodu snížení přenosu dat, mezi klientem a SQL serverem, v podstatě vše z CSV nasypat do jakési TMP tabulky a pak už pracovat čistě v rámci SQL. Vidím tam ale problémy s kolizemi mezi různými uživateli (když se dva rozhodnou cosi aktualizovat naráz). V tomto případě by se navíc podle mně ani moc neušetřilo výkonu. Stejně by nakonec došlo k procházení řádek po řádku, jen z jiného zdroje.

Pro "zálohování" má dnes Joomla již vlastní princip verzování - ten by byl možná zajímavý zapracovat...

Pro možnost přispívání do fóra je nutné: Přihlásit se nebo Vytvořit účet.