Dubletten vermeiden in sqlite

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Trubinial Guru
User
Beiträge: 117
Registriert: Dienstag 7. April 2009, 13:40

Hallo, ich habe eine kleine Tabelle mit den Spalten Primary Key, Key, Value, Changed. Ab und an wird versucht eine Reihe hinzuzufügen, wobei die Zeile nur dann hinzugefügt werden soll, wenn noch keine Reihe mit den selben Key-Wert vorhanden ist. Somit sollen Dubletten vermieden werden. In der Spalte Value dürfen Einträge mehrfach vorkommen.

Ich hatte es so verstanden, dass ich der Zeile, in der kein Eintrag mehrfach auftauchen darf, ein UNIQUE zuordne und dann immer über INSERT OR IGNORE eine Reihe hinzufüge, wenn es noch keine Reihe mit dem selben Key-Wert gibt.

Die Tabelle habe ich also so erstellt:

Code: Alles auswählen

CREATE TABLE IF NOT EXISTS configTable (
    id INTEGER PRIMARY KEY,
    key TEXT UNIQUE,
    value TEXT,
    changed INTEGER
  )


und die Reihe habe ich so hinzugefügt:

Code: Alles auswählen

INSERT OR IGNORE 
INTO configTable (key, value, changed) VALUES (
?, ?, ?
) 
Nur leider sorgt das nur dazu, dass die Reihe immer hinzugefügt wird - egal ob schon eine Reihe mit dem selben Key-Wert vorhanden ist. Liegt der Fehler woanders oder habe ich das einfach falsch verstanden?

Vielen Dank
Zuletzt geändert von Anonymous am Dienstag 26. Februar 2013, 14:25, insgesamt 1-mal geändert.
Grund: Code-Formatierung korrigiert
Benutzeravatar
noisefloor
User
Beiträge: 4149
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wenn der "key" eindeutig ist (sein muss), dann mach' ihn zum "primary key". Das ist ja genau der Sinn eines primary keys ;-)

Gruß, noisefloor
Trubinial Guru
User
Beiträge: 117
Registriert: Dienstag 7. April 2009, 13:40

Macht nicht nur Sinn, sondern funktioniert sogar auch :D Danke dir!

Nur interessehalber die Frage : wofür ist denn dann UNIQUE?
Benutzeravatar
noisefloor
User
Beiträge: 4149
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

einen primary key darf es nur genau 1x geben, UNIQUE darf pro Tabelle beliebig oft vorkommen. Siehe auch z.B. http://www.w3schools.com/sql/sql_unique.asp

Gruß, noisefloor
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Trubinial Guru,

nur der Vollständigkeit halber. Bei mir tut UNIQUE was es soll:

Code: Alles auswählen

>>> db=sqlite3.Connection('test.db')
>>> cur=db.cursor()
>>> cur.execute('''CREATE TABLE IF NOT EXISTS configTable (
...     id INTEGER PRIMARY KEY,
...     key TEXT UNIQUE,
...     value TEXT,
...     changed INTEGER
...   )''')
<sqlite3.Cursor object at 0x10ef335e0>
>>> cur.execute("insert into configTable values (null,'k','v',1)")
<sqlite3.Cursor object at 0x10ef335e0>
>>> cur.execute("insert into configTable values (null,'k','w',2)")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.IntegrityError: column key is not unique
Trubinial Guru
User
Beiträge: 117
Registriert: Dienstag 7. April 2009, 13:40

Hallo, ich habe gemerkt, dass ich doch noch ein anderes Szenario beachten muss. Undzwar darf ein "key" in Kombination mit dem Wert der neuen Spalte "userID" nicht mehrfach vorkommen.

Beispiel:
Folgendes ist erlaubt:

Key userID
--------------------------
A _____ 1
A _____ 2
B _____ 1


Folgendes darf nicht passieren:

Key userID
--------------------------
A _____ 1
A _____ 1
B _____ 1


Gibt es da einen einfachen Weg, dass zu lösen oder muss ich mir da was passendes selber schreiben?
Zuletzt geändert von Trubinial Guru am Dienstag 5. März 2013, 21:25, insgesamt 4-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich weiß nicht, ob SQLite es unterstzützt, aber prinzipiell sollte es so gehen:

Code: Alles auswählen

CREATE TABLE eggs(
    spam INTEGER,
    ham INTEGER,
    value INTEGER,
    UNIQUE KEY(spam, ham));
Das Leben ist wie ein Tennisball.
Trubinial Guru
User
Beiträge: 117
Registriert: Dienstag 7. April 2009, 13:40

So scheint es leider nicht zu funktionieren (OperationalError). Auch würde doch das erste Beispiel dann nicht gehen ... :K
Benutzeravatar
noisefloor
User
Beiträge: 4149
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

musst du eigentlich SQLite nehmen?

Diese Arten von Daten ließe sich sehr elegant mit Redis speichern, wenn du als Datentyp ein Set nimmst.

Gruß, noisefloor
Trubinial Guru
User
Beiträge: 117
Registriert: Dienstag 7. April 2009, 13:40

Ja, ich bin leider auf SQLite angewiesen - notfalls muss ich das Problem wohl irgendwie umgehen ...

Trotzdem danke euch
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann übernehme ich das mal. Was genau sind denn jetzt deine Anforderungen? Für mich sieht es so aus, als wenn das Tuple (key, userID) eindeutig sein muss.
Das Leben ist wie ein Tennisball.
Antworten