Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Lysander schrieb: Wie es aussieht ist das ein Fehler im SQLite Manager! Bist Du Dir sicher, dass dort die DB auch entsprechend aktuell ist? Evtl. ist dort die Tabelle anders definiert?
Im SQLite Manager ist das Feld korrekterweise als Primary Key definiert und die Datenbank ist auch aktuell. Entspricht 1:1 meiner Datenbank, welche ich mittels Python generiert habe. Ist also ein Fehler vom SQLite Manager. Andere Frage: Kann ich einen Datensatz mit Python in SQLite abändern, wobei ich natürlich nur den Wert des Feldes "id" abändern will, sodass man evtl. 2 Datensätze mit gleichem PK erzeugen kann?
An Deiner Stelle solltest Du Dir mal etwas über Keys durchlesen - letztlich ist das die Grundlage für relationale Datenbanken.
Ich entwickle halt lieber mit chaotischen Datenbanken 😉 Nein, Scherz. Ab jetzt muss ich halt Primary Keys wohl verwenden. Allerdings stellt sich mir eine Frage: Wieso kann ich überhaupt eine Datenbank ohne Primary Key erstellen? Würde da schon eine Exception ausgelöst, dann hätte man solche streitereien rund um Primary Key erst gar nicht.... mfg
|
oliver1804
Anmeldungsdatum: 27. März 2006
Beiträge: 279
Wohnort: Elmshorn
|
Wieso kann ich überhaupt eine Datenbank ohne Primary Key erstellen?
es gibt einen internen PK, den man bspw. über ROWID abfragen kann - ansonsten gilt: je mehr Freiheit desto besser (natürlich hat das auch so seine Tücken ☺ )
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
oliver1804 schrieb:
Wieso kann ich überhaupt eine Datenbank ohne Primary Key erstellen?
es gibt einen internen PK, den man bspw. über ROWID abfragen kann - ansonsten gilt: je mehr Freiheit desto besser (natürlich hat das auch so seine Tücken ☺ )
Achso, ok. Trotzdem bleibt die Frage, welcher Sinn hinter einem PrimaryKey liegt, wenn man diesen 1. gar nicht definieren muss, obwohl man es sollte 2. man ihn überschreiben kann, sodass die DB inkonsistent wird Freiheit an sich ist ja gut, aber trotzdem sollte man den User wenigstens Warnen, wenn er was dummes vorhat (wie zum Beispiel keinen PrimaryKey verwenden, dupdidu 😈 ) Ich sag dann jetzt auch mal gute Nacht, mfg
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
TDeveloper schrieb:
Trotzdem bleibt die Frage, welcher Sinn hinter einem PrimaryKey liegt, wenn man diesen 1. gar nicht definieren muss, obwohl man es sollte
Naja, manchmal muss man eben ohne Nanny die richtige Entscheidung treffen. Bei relationalen DBs setzt das immer eine gute Planung im Vorfeld voraus, bei der die später benutzte Struktur festgezurrt wird. Und da plant man eben Keys ein.
2. man ihn überschreiben kann, sodass die DB inkonsistent wird
Vorsicht. Solange er unique bleibt, ist da nix inkonsistent. Bei der Manipulation eines PK in einer Tabelle, müssen halt nur ggf. Forgein Keys in anderen geändert werden. Dafür gibt es Trigger, wie etwa on ... cascade usw.
Freiheit an sich ist ja gut, aber trotzdem sollte man den User wenigstens Warnen, wenn er was dummes vorhat (wie zum Beispiel keinen PrimaryKey verwenden, dupdidu 😈 )
Wie gesagt, der SQLiteManager ist ja nun keine default Implementierung. Ich nehme an das Tool sqlite - die Referenzimplementierung - dürfte einen da warnen. Davon abgesehen gilt eben obiges. Bei der Planung spielen Keys im relationalen Konzept die zentrale Rolle.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Lysander schrieb: TDeveloper schrieb: Freiheit an sich ist ja gut, aber trotzdem sollte man den User wenigstens Warnen, wenn er was dummes vorhat (wie zum Beispiel keinen PrimaryKey verwenden, dupdidu 😈 )
Wie gesagt, der SQLiteManager ist ja nun keine default Implementierung. Ich nehme an das Tool sqlite - die Referenzimplementierung - dürfte einen da warnen. Davon abgesehen gilt eben obiges. Bei der Planung spielen Keys im relationalen Konzept die zentrale Rolle.
Wenn ich endlich weiß, wie man einen Datensatz updaten kann, dann würde man sehen ob eine Warnung ausgegeben wird oder nicht. Sprich, wenn man nen vorhandenen Datensatz einfach die ID auf eine bereits vorhandene setzt. Wenn da dann keine Warnung ausgegeben wird, dann wärs vielleicht ein Bug-Report Wert. Evtl. weißt du wie das geht? Ich kommt mit dem replace/update nicht klar (was ich auch mache, es gibt immer ne Fehlermeldung) mfg
|
762378
Anmeldungsdatum: 7. September 2010
Beiträge: 127
|
Ich werfe jetzt mal kurz gefährliches Halbwissen ein: Wenn du sagst, dass die Datenbank "einige Millionen Einträge" haben wird, macht es da nicht schon fast Sinn, einen Datenbankserver wie Postgres oder MySQL ein zu setzen? Wenn du jetzt mit rohem SQL gegen SQLite entwickelst und später auf Postgres oder MYSQL schwenken willst, musst du aufpassen dass dir die Querys nicht um die Ohren fliegen, denn nicht jede Datenbank unterstützt den gleichen Befehlssatz. Am besten nutzt du direkt SQLAlchemy 😉
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
TDeveloper schrieb: Wenn ich endlich weiß, wie man einen Datensatz updaten kann, dann würde man sehen ob eine Warnung ausgegeben wird oder nicht. Sprich, wenn man nen vorhandenen Datensatz einfach die ID auf eine bereits vorhandene setzt. Wenn da dann keine Warnung ausgegeben wird, dann wärs vielleicht ein Bug-Report Wert. Evtl. weißt du wie das geht? Ich kommt mit dem replace/update nicht klar (was ich auch mache, es gibt immer ne Fehlermeldung)
Wie sieht die denn aus? Welcher Code wird ausgeführt? ❓ @762378 Die reine Anzahl an Datensätzen spiel da keine Rolle. Auch SQLite kann mehrere Millionen Datensätze beherrschen 😉 SQLAlchemy ist aber natürlich immer einen Blick wert!
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
So, mal ein Beispiel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 | In [4]: import sqlite3
In [5]: sqlite3.connect
sqlite3.connect
In [5]: con = sqlite3.connect(":memory:")
In [6]: c = con.cursor()
In [7]: c.execute(u"""
...: create table foo (
...: id integer,
...: data text,
...: primary key(id)
...: )
...: """)
Out[8]: <sqlite3.Cursor object at 0x9737520>
In [9]: c.execute("insert into foo values (0, 'lalala')")
Out[9]: <sqlite3.Cursor object at 0x9737520>
In [10]: c.execute("insert into foo values (1, 'lalala')")
Out[10]: <sqlite3.Cursor object at 0x9737520>
In [11]: c.execute("insert into foo values (1, 'lalala')")
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
/home/nelson/<ipython console> in <module>()
IntegrityError: PRIMARY KEY must be unique
In [16]: c.execute("update foo set id=2 where id=1")
Out[16]: <sqlite3.Cursor object at 0x9737520>
In [17]: res = c.execute("select id, data from foo")
In [18]: res
Out[18]: <sqlite3.Cursor object at 0x9737520>
In [19]: for item in res.fetchall():
....: print item
....:
....:
(0, u'lalala')
(2, u'lalala')
In [24]: c.execute("update foo set id=0 where id=2")
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
/home/nelson/<ipython console> in <module>()
IntegrityError: PRIMARY KEY must be unique
|
Damit ist klar, dass das sqlite3 -Modul von Python einen Fehler vermeldet, wenn man den PK dermaßen verändert, dass die unique -Eigenschaft verletzt würde. QED.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
762378 schrieb: Ich werfe jetzt mal kurz gefährliches Halbwissen ein: Wenn du sagst, dass die Datenbank "einige Millionen Einträge" haben wird, macht es da nicht schon fast Sinn, einen Datenbankserver wie Postgres oder MySQL ein zu setzen? Wenn du jetzt mit rohem SQL gegen SQLite entwickelst und später auf Postgres oder MYSQL schwenken willst, musst du aufpassen dass dir die Querys nicht um die Ohren fliegen, denn nicht jede Datenbank unterstützt den gleichen Befehlssatz. Am besten nutzt du direkt SQLAlchemy 😉
Um ehrlich zu sein will ich eben keinen Datenbankserver haben. Heißt soviel wie: kein MySQL, kein Postgres. SQLite braucht eben keinen Server, deshalb war es für mich die passende Wahl ☺ SQLAlchemy kenn ich im übrigen (noch) nicht. Muss ich mir mal anschauen. Achja, und wegen dem Befehlssatz: Ich denke, das lässt sich relativ leicht anpassen. Befehle wie INSERT oder CREATE TABLE bzw. SELECT werden ja wohl in allen Datenbanken relativ gleich sein, oder? Lysander schrieb: TDeveloper schrieb: Evtl. weißt du wie das geht? Ich kommt mit dem replace/update nicht klar (was ich auch mache, es gibt immer ne Fehlermeldung)
Wie sieht die denn aus? Welcher Code wird ausgeführt? ❓
Den Code hab ich schon wieder verworfen (weil er eben nicht funktioniert hat). Ich weiß noch, dass es angefangen hat mit "INSERT OR REPLACE INTO ", aber as wars auch schon. Wenn du weißt, wie man nen bestehenden Datensatz ändern kann, dann immer her damit. Tabelle hatte übrigens ein Feld id (integer, autoincrement, primary key) und ein feld zahl (integer). Und ich wollt die ID ändern auf eine bestehnde (um eben zu sehen, ob eine Warnung ausgegeben wird) mfg
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
TDeveloper schrieb: Den Code hab ich schon wieder verworfen (weil er eben nicht funktioniert hat).
Nuja, ohne Code und ohne exakte zugehörige Fehlermeldung kann man eigentlich nie etwas sinnvolles dazu sagen. Also wenn Du Fragen dazu hast, musst Du das schon liefern 😉
Ich weiß noch, dass es angefangen hat mit "INSERT OR REPLACE INTO ", aber as wars auch schon. Wenn du weißt, wie man nen bestehenden Datensatz ändern kann, dann immer her damit.
s. mein Posting oben oder eben auch den kommenden 😉 So, habs mal mit sqlite ausprobiert (dem Konsolentool):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | sqlite> create table foo (
...> id integer,
...> data text,
...> primary key(id)
...> )
...> ;
sqlite> show
...> ;
SQL error: near "show": syntax error
sqlite> .show;
unknown command or invalid arguments: "show;". Enter ".help" for help
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main
1 temp
sqlite> insert into foo values (0, "lalala");
sqlite> insert into foo values (0, "lalala");
SQL error: PRIMARY KEY must be unique
sqlite> insert into foo values (1, "lalalaasfsa");
sqlite> select * from foo;
0|lalala
1|lalalaasfsa
sqlite> update foo set id=2 where id=1;
sqlite> select * from foo;
0|lalala
2|lalalaasfsa
sqlite> update foo set id=0 where id=2;
SQL error: PRIMARY KEY must be unique
|
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Fiel mir grad noch ein: Link Die Beiträge von ihm sind imho immer lesenswert.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Ah, danke. Ich hab das mal in Python nachgebastelt: | >>> cursor.execute('UPDATE test SET id=2 WHERE id=1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
sqlite3.IntegrityError: PRIMARY KEY must be unique
>>>
|
Aber komisch dass es dann im SQLite-Manager funktioniert. Sollte nicht so sein. Hab übrigens jetzt ein funktionierendes Beispiel für Replace: | cursor.execute('INSERT OR REPLACE INTO test ("id", "zahl") VALUES (1, 5)')
|
Das setzt bei mir das Feld "zahl" bei dem Datensatz mit der ID 1 auf 5. Komisch, dass ich das vorher nicht zusammengebracht habe 🙄 mfg EDIT: Was ich noch fragen wollte: Wie beende ich die Verbindung zur Datenbank richtig? Genügt ein connection.close() oder muss vorher ein cursor.close() gemacht werden oder ist das egal?
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
TDeveloper schrieb: Aber komisch dass es dann im SQLite-Manager funktioniert. Sollte nicht so sein.
Wie ich schon schrieb, kann man das wohl als Bug bezeichnen.
EDIT: Was ich noch fragen wollte: Wie beende ich die Verbindung zur Datenbank richtig? Genügt ein connection.close() oder muss vorher ein cursor.close() gemacht werden oder ist das egal?
Die Verbindung zu einer DB schließt Du mit der close -Methode auf dem connection -Objekt. Aber ein cursor -Objekt kennt eben auch eine close -Methode. Man kann davon ja mehrere auf einer Connection haben. Sauber ist es, immer alles zu schließen.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Lysander schrieb: Die Verbindung zu einer DB schließt Du mit der close -Methode auf dem connection -Objekt. Aber ein cursor -Objekt kennt eben auch eine close -Methode. Man kann davon ja mehrere auf einer Connection haben. Sauber ist es, immer alles zu schließen.
Hm, irgendwie hab ich mir genau sowas gedacht. mfg
|