ubuntuusers.de

Python + SQLite: Datensatz 1 bis x ausgeben

Status: Gelöst | Ubuntu-Version: Ubuntu 11.04 (Natty Narwhal)
Antworten |

Developer92 Team-Icon

(Themenstarter)
Avatar von Developer92

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 Team-Icon

(Themenstarter)
Avatar von Developer92

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

Avatar von 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 Team-Icon

(Themenstarter)
Avatar von Developer92

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

Avatar von 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

Avatar von 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 Team-Icon

(Themenstarter)
Avatar von Developer92

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

Avatar von 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

Avatar von 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 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Ah, danke. Ich hab das mal in Python nachgebastelt:

1
2
3
4
5
>>> 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:

1
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

Avatar von 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 Team-Icon

(Themenstarter)
Avatar von Developer92

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

Antworten |