Stránka: 1 z 1
| [ Príspevkov: 23 ] | |
Autor | Správa |
---|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Dostal som sa s mojou prvou appkou do bodu, kde riesim akym sposobom ukladat vysledky merani do databazy. Ide o to ze nevieme dopredu kolko vysledkov (konkretne medzicasov) budeme mat v jednom merani. Pocet medzicasov v jednom merani moze byt vzdy rozny. Ako by ste navrhli vytvorit strukturu databazi? Mna napada toto: 1, Vytvorit pre kazde meranie osobitnu tabulku a pocet riadkov tabulky bude pocet medzicasov merania. 2, Vsetky merania zapisovat do jednej tabulky, pocet riadkov bude pocet medzicasov vsetkych merani dokopy, ale bude tam stlpec navyse a v nom bude cislo merania. Napr. prve tri riadky bude 1. meranie, dalsich 5 riadkov bude 2. meranie, atd. 3, Vsetky merania do jednej tabulky, pricom jeden riadok obsahuje cele jedno meranie a vsetky medzicasy jedneho merania su vlozene ako objekt, napr. pole typu String[] do jednej bunky: Kód: Table: Merania Id | Date | Times | 1 | 15.4. | String[] | 2 | 17.4. | String[] | 2 | 19.4. | String[] |
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno |
2 je spravne. Pozri si nieco o normalnych formach (trojka nedodrzuje ani 1. NF a jednotka je taka strasna blbost, ze v normalnych formach sa o tom ani nehovori ). Presuvam do databaz (rozmyslam, co ta inspirovalo zaradit to inam).
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Aha sorry, robim to v jave a neuvedomil som si ze toto uz neni o jave ale o databazach. Myslel som si z to bude 1. moznost a preco je to taka blbost, je to v niecom neprakticke? Teoreticky by bola mozna aj 3.: Citácia: You'll need to be able to serialize your object into a byte stream and then recreate your object from a byte stream.
Then, just store that byte stream in your db.
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno |
Vo vsetkom. Budes chciet vediet pocet merani a co? Budes sa hrabat v systemovych tabulkach a selectovat nazvy existujucich tabuliek? Wtf. Alebo budes chciet pocet vsetkych medzicasov a uz si neviem predstavit, ako by si to robil. Ak by si chcel dalej k jednotlivym medzicasom poznamenat, kto to zabehol, budes modifikovat strukturu tristo tabuliek? Atd atd. Prakticky by to moznost 3 nebola, isto to pisal nejaky bastlic Javista, co databazu nevidel ani na obrazku... serializacia objektu ti vypluje nejaky binarny bordel, s ktorym nemozes robit vobec nic, nijak to vyhladavat, nijak to preniest, dokaze s tym manipulovat iba ta Java zase. Ak by si chcel vyhladavat vsetky medzicasy vacsie ako 10 minut, co narobis? Musel by si nasosat z DB vsetky data a nechat v tom hladat svoj program, ale DB server to spravi stokrat rychlejsie a efektivnejsie, lebo je na to robeny.
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Aha jasne..
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 05.10.06 Prihlásený: 15.10.18 Príspevky: 1891 Témy: 148 | 148 Bydlisko: Bratislava |
Pred tym ako zacnes robit nejake DB si naozaj nastuduj normalizaciu DB a riad sa prvymi troma normalnymi formami. Vyhnes sa kope problemom v buducnosti.
Co sa tyka 3ky, tak si myslim ze by sa dala modifikovat.. Mal by si 1 riadok na 1 meranie a medzicasy by boli v JSONe. S JSONom mozes velmi sikovne pracovat napr pomocou knznice Gson. Su aj ine ale ja pouzivam v androide tuto. Myslim si ze toto riesenie by nebol az taky fail, DB by bola mensia, ale pracoval by si viac s jsonom a menej s DB. Najjednoduchsiu robotu budes mat s 2kou.
_________________ Notebook Dell 7537, 24" BenQ BL2411PT, Logitech Illuminated keyboard, Razer DeathAdder, Razer Goliathus, Koss Porta Pro |
|
Registrovaný: 23.09.13 Prihlásený: 04.12.14 Príspevky: 68 Témy: 1 | 1 |
Ani jedno riesenie nie je spravne. Spravne riesenie su dve tabulky prepojene cez foreign key.
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Myslim ze to urobim takto: Kód: ID | Meranie | Datum | Cas | Aktivita | 1 | 1 | 25.4. | 00:00:15 | beh | 2 | 1 | null | 00:00:45 | null | 3 | 1 | null | 00:01:20 | null | 1 | 2 | 27.4. | 00:00:11 | plavanie | 2 | 2 | null | 00:00:22 | null | 1 | 3 | 1.5. | 00:00:15 | cyklistika | 2 | 3 | null | 00:00:16 | null | 3 | 3 | null | 00:00:17 | null | 4 | 3 | null | 00:00:18 | null |
kde ID urcuje poradie medzicasov konkretneho merania.
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 27.07.07 Príspevky: 3948 Témy: 51 | 51 Bydlisko: Bratislava |
Z tohto navrhu uz jasne vidno, ze to nie je spravne riesenie. Pozri, kolko tam mas zbytocnych null hodnot. ChickenHunter79 ma pravdu, v tomto pripade treba 2 tabulky, jedna na vysledky jednotlivych merani (cas, pripadne poradove cislo, to ale nemusi byt), druha na info o samotnom merani (aktivita, datum) a navzajom prepojene cislom merania.
_________________ NTB: Acer Aspire 4820TG 14" | CPU: Intel Core i5 2,53 GHz | VGA: ATI Mobility Radeon HD5650 1GB | RAM: 8GB DDR3 1066 MHz | HDD: 1TB SSD WD BLUE |
|
Registrovaný: 05.10.06 Prihlásený: 15.10.18 Príspevky: 1891 Témy: 148 | 148 Bydlisko: Bratislava |
Keby si pozrel normalizaciu, tak by na to dosiel aj sam
_________________ Notebook Dell 7537, 24" BenQ BL2411PT, Logitech Illuminated keyboard, Razer DeathAdder, Razer Goliathus, Koss Porta Pro |
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Hej len kvoli jednoduchosti programovania som to chcel mat v jednej tabulke ale tak mozno ze to spravim aj pomocou 2 tabuliek. A to prepojenie treba nejak explicitne nastavit, nestaci ze do obidvoch tabuliek sa bude vkladat cislo merania?
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno |
Preboha, a ja som tak nejak dufal, ze v dvojke myslis na to, ze tie merania budes mat v inej tabulke. Nie mozno, ale urcite to tak sprav. Dve tabulky ti v tomto pripade programovanie urcite neskomplikuju, ale ulahcia - daj si povedat, prides na to casom. Prepojis to akurat tym foreign klucom, ktory explicitne urcujes v definicii tabulky, to urcite vygooglis. On tam vlastne byt nemusi, ale je pre zachovanie konzistencie dat velmi dolezity.
Kamahl, samozrejme dobre hovoris, nicmene u komplexnejsieho systemu dojdes po nejakom case k tomu, ze z performance dovodov nemas sancu 3. NF vzdy dodrzat. (Cim nechcem povedat, ze by si ju nemal incredible nastudovat a drzat sa jej ; ) Jo a ten JSON, nesuhlasim s tym, ze by to nebol az taky fail - je to totalny fail. Hovoris mu o NF a potom vravis, ze by nebol az taky fail nedodrziavat ani tu prvu. Ved s tym sa neda vobec nic.
|
|
Registrovaný: 05.10.06 Prihlásený: 15.10.18 Príspevky: 1891 Témy: 148 | 148 Bydlisko: Bratislava |
Ja som za NF ale 100 ludi, 100 chuti keby toto konkretne zadanie robil jsonom tak si az tak neuskodi dokonca by mal mensiu db. Ale samozrejme json nebol vymysleny na ukladanie dat do db..
_________________ Notebook Dell 7537, 24" BenQ BL2411PT, Logitech Illuminated keyboard, Razer DeathAdder, Razer Goliathus, Koss Porta Pro |
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Takto? Kód: CREATE TABLE StopwatchEvents (Event INTEGER PRIMARY KEY AUTO INCREMENT, DateTime TEXT, Activity TEXT) CREATE TABLE StopwatchSplits (Event INTEGER, Splits TEXT, FOREIGN KEY (Event) REFERENCES StopwatchEvents(Event))
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 05.04.11 Príspevky: 1693 Témy: 50 | 50 Bydlisko: Žilina, Pop... | |
Registrovaný: 23.09.13 Prihlásený: 04.12.14 Príspevky: 68 Témy: 1 | 1 |
incredible píše: Takto? Kód: CREATE TABLE StopwatchEvents (Event INTEGER PRIMARY KEY AUTO INCREMENT, DateTime TEXT, Activity TEXT) CREATE TABLE StopwatchSplits (Event INTEGER, Splits TEXT, FOREIGN KEY (Event) REFERENCES StopwatchEvents(Event)) - Kazda tabulka by mala mat Id cize aj StopwatchSplits - tabulky pomenuvaj v jednotnom cisle, kazdy vie, ze tam nebude len jeden zaznam. - stlpec Event je Id tak mu daj prefix alebo sufix Id - DateTime je datovy typ, tak slpec nazvi inak, a daj mu typ Date (DateTime ...) nie TEXT - Stlpec Splits je co? Nema tam byt dlzka trvania jedneho medzicasu, napr. v milisekundach? Dufam, ze ta nezavadzam moc ohladom datovych typov SQLLite ja poznam len MSSQL
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
V SQLite nie su ziadne datove typy, resp. datovy typ sa ignoruje a automaticky sa vsetko uklada bud ako cislo alebo text. A split je po anglicky medzičas.
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno |
ChickenHunter79 píše: - Kazda tabulka by mala mat Id cize aj StopwatchSplits Preco by nutne musela? Keby si povedal, ze kazdy tabulka by mala mat PK, tak suhlasim. Ale ak by sa rozhodol, ze ten PK bude dvojica (event_id, poradie_pokusu), kde to poradie_pokusu bude jedinecne iba v ramci eventu, ale nie v ramci celej tabulky, tak je to imho uplne v poriadku.
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Takze zatial mam takyto kod v MainActivity: Kód: datahelper = new SRSSQLiteHelper(getApplicationContext()); database = datahelper.getWritableDatabase();
if (program.equals("stopwatch")) { datahelper.insert_stopwatch(getApplicationContext(),times_list,database); } if (program.equals("timer")) { datahelper.insert_timer(getApplicationContext(),times_list, database); } a k tomu takuto triedu: Kód: public class SRSSQLiteHelper extends SQLiteOpenHelper {
private static final String DATABAZE_NAME = "SRSdatabaze"; private static final int DATABAZE_VERSION = 1; Context myContext;
private static final String CREATE_TABLES = "CREATE TABLE StopwatchEvents (Event_ID INTEGER PRIMARY KEY AUTOINCREMENT, Date_time TEXT, Activity TEXT, Duration TEXT, Splits_count INTEGER) " + "CREATE TABLE StopwatchSplits (Event INTEGER, Splits TEXT, FOREIGN KEY (Event) REFERENCES StopwatchEvents(Event))" + "CREATE TABLE TimerEvents (Event INTEGER PRIMARY KEY AUTOINCREMENT, DateTime TEXT, Activity TEXT, Duration TEXT, Pauses_count INTEGER)" + "CREATE TABLE TimerPauses (Event INTEGER, Pauses TEXT, FOREIGN KEY (Event) REFERENCES TimerEvents(Event_ID)";
public SRSSQLiteHelper(Context context) { super(context, DATABAZE_NAME, null, DATABAZE_VERSION); Toast.makeText(context,"SRSSQLiteHelper constructor", Toast.LENGTH_SHORT).show(); myContext=context; }
@Override public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLES); Toast.makeText(myContext,"SRSSQLiteHelper constructor", Toast.LENGTH_SHORT).show();
}
@Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {
}
public void insert_stopwatch(Context context,ListView listview, SQLiteDatabase db) {
Adapter adapter = listview.getAdapter(); int splits_count = adapter.getCount(); String date_time = this.getDate_Time(); String duration = adapter.getItem(splits_count-1).toString();
db.execSQL("INSERT INTO StopwatchEvents (Date_time, Duration, Splits_count) VALUES ('"+date_time+"','"+duration+"',"+splits_count+")");
int i=0; while (i<splits_count) {
String time = adapter.getItem(i).toString(); db.execSQL("INSERT INTO StopwatchSplits (Event, Splits) VALUES (1,'"+time+"')");
} Toast.makeText(context, "adding " + Integer.toString(i) + " rows",Toast.LENGTH_SHORT).show();
}
public void insert_timer(Context context, ListView listview, SQLiteDatabase db) {}
public String getDate_Time(){
Date dnow = new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss"); return df.format(dnow);
} } Ked som to spustil tak mi to pise takuto chybu: Citácia: Caused by: android.database.sqlite.SQLiteException: near "CREATE": syntax error (code 1): , while compiling: CREATE TABLE StopwatchEvents (Event_ID INTEGER PRIMARY KEY AUTOINCREMENT, Date_time TEXT, Activity TEXT, Duration TEXT, Splits_count INTEGER) CREATE TABLE StopwatchSplits (Event INTEGER, Splits TEXT, FOREIGN KEY (Event) REFERENCES StopwatchEvents(Event))CREATE TABLE TimerEvents (Event INTEGER PRIMARY KEY AUTOINCREMENT, DateTime TEXT, Activity TEXT, Duration TEXT, Pauses_count INTEGER)CREATE TABLE TimerPauses (Event INTEGER, Pauses TEXT, FOREIGN KEY (Event) REFERENCES TimerEvents(Event_ID) Co tam mam niekde nejaku syntakticku chybu ci co?
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno |
No mas, nie je to jeden prikaz, ale styri. V prvom rade by som ich skusil oddelit bodkociarkou. Myslim si ale, ze ani to nepomoze, vacsinou nemozes vykonat viac DDL/DML prikazov naraz. Asi budes musiet to execSQL volat styrikrat. Citácia: Kód: db.execSQL("INSERT INTO StopwatchEvents (Date_time, Duration, Splits_count) VALUES ('"+date_time+"','"+duration+"',"+splits_count+")"); No a toto je samozrejme uplna prasarna a nabeh na obrovsku bezpecnostnu dieru. Pozri si nieco o prepared statements.
|
|
Registrovaný: 11.02.09 Prihlásený: 12.11.24 Príspevky: 2208 Témy: 145 | 145 Bydlisko: Liptovský M... |
Takze som to rozdelil na 4 prikazy a uz to funguje. Tie stringy v execSQL() si este popridavam do premennych. Zatial mam takuto metodu ktora pridava do stlpca Event v tabulke StopwatchSplits vzdy to iste cislo - 1: Kód: public void insert_stopwatch(Context context,ListView listview, SQLiteDatabase db) {
Adapter adapter = listview.getAdapter(); int splits_count = adapter.getCount(); String date_time = this.getDate_Time(); String duration = adapter.getItem(splits_count-1).toString();
db.execSQL("INSERT INTO StopwatchEvents (Date_time, Duration, Splits_count) VALUES ('"+date_time+"','"+duration+"',"+splits_count+")");
int i=0; while (i<splits_count) { String time = adapter.getItem(i).toString(); db.execSQL("INSERT INTO StopwatchSplits (Event, Splits) VALUES (1,'"+time+"')"); i++; } Toast.makeText(context, "adding " + Integer.toString(i) + " rows",Toast.LENGTH_SHORT).show(); }
Teraz rozmyslam, ako co najjednoduchsie spravit to, aby sa tam pridalo vzdy take cislo ako ma Event_ID v tabulke StopwatchEvents. Neda sa to dako automaticky ked je tam nastaveny ten foreign key? Btw. da sa nejako zobrazit obsah tej databazi v Android Studiu?
_________________ "Only a warrior chooses pacifism, others are condemned to it." - unknown author |
|
Registrovaný: 11.08.07 Príspevky: 4088 Témy: 34 | 34 Bydlisko: Brno | |
Registrovaný: 05.10.06 Prihlásený: 15.10.18 Príspevky: 1891 Témy: 148 | 148 Bydlisko: Bratislava |
preco nepouzijes funkciu insert() z SQLiteDatabase? Hodim ti sem nejaky kod z mojej prvej android appky, je tam praca s DB aj insert() Kód: package com.example.wiki.map;
import java.util.ArrayList; import java.util.HashMap;
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase;
public class BookmarksDataSource {
private SQLiteDatabase database; private MySQLiteHelper dbHelper; private Context mContext; private String[] allColumns = { MySQLiteHelper.COLUMN_ID, MySQLiteHelper.COLUMN_TITLE, MySQLiteHelper.COLUMN_URL, MySQLiteHelper.COLUMN_LAT, MySQLiteHelper.COLUMN_LNG };
public BookmarksDataSource(Context context) { mContext = context; dbHelper = new MySQLiteHelper(mContext); }
public void open() throws SQLException { database = dbHelper.getWritableDatabase(); }
public void close() { dbHelper.close(); }
public Bookmark createBookmark(String title, String url, String latitude, String longitude) { ContentValues values = new ContentValues(); values.put(MySQLiteHelper.COLUMN_TITLE, title); values.put(MySQLiteHelper.COLUMN_URL, url); values.put(MySQLiteHelper.COLUMN_LAT, latitude); values.put(MySQLiteHelper.COLUMN_LNG, longitude); long insertId = database.insert(MySQLiteHelper.TABLE_BOOKMARKS, null, values); Cursor cursor = database.query(MySQLiteHelper.TABLE_BOOKMARKS, allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null, null, null, null); cursor.moveToFirst(); Bookmark newBookmark = cursorToBookmark(cursor); cursor.close();
return newBookmark; }
public void deleteBookmark(String bookmarkId) { long id = Long.valueOf(bookmarkId).longValue();; database.delete(MySQLiteHelper.TABLE_BOOKMARKS, MySQLiteHelper.COLUMN_ID + " = " + id, null); }
public ArrayList<HashMap<String, String>> getAllBookmarks() { ArrayList<HashMap<String, String>> bookmarks = new ArrayList<HashMap<String, String>>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_BOOKMARKS, allColumns, null, null, null, null, null);
cursor.moveToFirst(); while ( !cursor.isAfterLast()) { Bookmark bookmark = cursorToBookmark(cursor); HashMap<String, String> map = new HashMap<String, String>(); map.put("id", bookmark.getId()+""); map.put("title", bookmark.getTitle()); map.put("url", bookmark.getUrl()); String location = mContext.getString(R.string.latitude) + " " + bookmark.getLatitude() + " " + mContext.getString(R.string.longitude) + " " + bookmark.getLongitude(); map.put("location", location); bookmarks.add(map);
cursor.moveToNext(); } cursor.close(); return bookmarks; }
private Bookmark cursorToBookmark(Cursor cursor) { Bookmark bookmark = new Bookmark(); bookmark.setId(cursor.getLong(0)); bookmark.setTitle(cursor.getString(1)); bookmark.setUrl(cursor.getString(2)); bookmark.setLatitude(cursor.getString(3)); bookmark.setLongitude(cursor.getString(4)); return bookmark; } }
_________________ Notebook Dell 7537, 24" BenQ BL2411PT, Logitech Illuminated keyboard, Razer DeathAdder, Razer Goliathus, Koss Porta Pro |
|
Stránka: 1 z 1
| [ Príspevkov: 23 ] | |
|