2009-05-10 10 views
3

Ich habe eine Liste von Zeichenfolgen in eine DB einfügen. Sie müssen einzigartig sein. Wenn ich einfüge möchte ich ihre ID (um als Fremdschlüssel in einer anderen Tabelle zu verwenden), also benutze ich last_insert_rowid. Ich bekomme 2 Probleme.Sqlite einfügen mit eindeutigen Namen, erhalten ID

  1. Wenn ich ersetzen, deren id (INTEGER PRIMARY KEY) Updates, die bricht meine db (Einträge nicht vorhandene IDs verweisen)
  2. Wenn ich ignorieren verwenden, Rowid nicht so nicht i aktualisiert wird erhalten die richtige ID

Wie bekomme ich ihre IDs? Wenn ich nicht brauche, würde ich nicht eine Select-Anweisung verwenden wollen, um die Zeichenfolge zu überprüfen und einzufügen, wenn sie nicht existiert. Wie soll ich das machen?

Antwort

3

Ich benutze die unten zur Zeit

insert into tbl(c_name) select 'val' where not exists(select id from tbl where c_name ='val'); 
select id from tbl where c_name ='val'; 
1

Mit "sie müssen eindeutig sein", meinen sie, Sie sind sicher, dass sie sind, oder dass Sie einen Fehler als Ergebnis haben möchten, wenn sie nicht sind? Wenn Sie nur die Zeichenfolge selbst zu einem Schlüssel in ihrer Tabelle machen, dann verstehe ich nicht, wie entweder 1 oder 2 ein Problem sein könnte - Sie erhalten einen Fehler im Falle unerwünschter Duplizierung, ansonsten die korrekte ID. Vielleicht können Sie Ihre Frage mit einem kleinen Beispiel für den von Ihnen verwendeten SQL-Code, der fraglichen Tabelle, dem beobachteten Verhalten und dem gewünschten Verhalten klären ...?

Bearbeitet: Danke für die Bearbeitung, aber es ist mir immer noch unklar, welche SQL Ihnen welche Probleme gibt! Wenn Ihre Tabelle herkommt, zB:

CREATE TABLE Foo(
    theid INTEGER PRIMARY KEY AUTOINCREMENT, 
    aword TEXT UNIQUE ABORT 
) 

dann jeder Versuch, eine duplizierte Wort INSERT fehl (das ABORT Schlüsselwort ist optional, da es für UNIQUE der Standard ist) - ist nicht das, was Sie wollenvorausgesetzt, Sie sagen die Worte "MUSS einzigartig sein", dh es ist ein Fehler, wenn sie nicht sind?

+0

anstelle eines Fehlers ich möchte last_insert_rowid mir die ID (PK) des Textes geben. Bisher ersetzt Ersetzen die ID, die vorherige Einträge unterbricht, und ein Fehler gibt die Rowid nicht zurück. Es klingt, als müsste ich das in zwei Schritten tun?eine select-Anweisung dann eine insert-Anweisung, falls sie nicht existiert –

8

Wenn eine UNIQUE-Constraint-Verletzung auftritt, löscht der REPLACE-Algorithmus bereits vorhandene Zeilen, die die Constraint-Verletzung verursachen, bevor die aktuelle Zeile eingefügt oder aktualisiert wird, und der Befehl wird normal ausgeführt. Dies bewirkt, dass die Rowid zu ändern und schafft das folgende Problem

Y:> **sqlite3 test** 
SQLite version 3.7.4 
Enter ".help" for instructions 
Enter SQL statements terminated with a ";" 
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE);** 
sqlite> **insert or replace into b values (null,'test-1');** 
sqlite> **select last_insert_rowid();** 
1 
sqlite> **insert or replace into b values (null,'test-2');** 
sqlite> **select last_insert_rowid();** 
2 
sqlite> **insert or replace into b values (null,'test-1');** 
sqlite> **select last_insert_rowid();** 
3 
sqlite> **select * from b;** 
2|test-2 
3|test-1 

Die Arbeit um ist die Definition der c2 Spalte zu ändern, wie

create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE); 

folgt und die „oder ersetzen“ Klausel zu entfernen aus Ihrem Einsätze;

dann, wenn Test nach dem Einsatz, müssen Sie die folgende SQL-auszuführen: select last_insert_rowid(), changes();

sqlite> **create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);** 
sqlite> **insert into b values (null,'test-1');** 
sqlite> **select last_insert_rowid(), changes();** 
1|1 
sqlite> **insert into b values (null,'test-2');** 
sqlite> **select last_insert_rowid(), changes();** 
2|1 
sqlite> **insert into b values (null,'test-1');** 
sqlite> **select last_insert_rowid(), changes();** 
2|0 

Der Rückgabewert der Änderungen nach dem dritten Einsatz wird eine Benachrichtigung an die Anwendung, die Sie benötigen, um Nachschlag das rowid von "test-1", da es bereits in der Datei war. Wenn es sich um ein Mehrbenutzersystem handelt, müssen Sie natürlich auch alles in eine Transaktion einbinden.

+0

Mit 'Einfügen oder Ersetzen in b-Werte (1, 'test-1');' Ich kann nichts über (1, val) wissen, also habe ich stattdessen null verwendet. Ich bekomme die gleichen Ergebnisse, wenn ich versuche, 'Einfügen oder Ersetzen in b (c2) Werte (val)' und 'Einfügen oder Ersetzen in b (c2) select val' mit den gleichen Ergebnissen. Hier ist ein Bild (warum kann ich nicht kopieren/einfügen in/aus sqlite-shell!) Http://i.imgur.com/2a6IY.png –

+0

folgen in Antwort bearbeitet: – Noah

+0

hmm, so dass ich im Grunde Änderungen überprüfen und wenn es 1 ist Ich benutze die Rowid, sonst brauche ich eine Select-Anweisung. Es klingt viel wie meine Antwort unten. Ok, das ist eine akzeptable Lösung, +1. Ich werde die aktuelle Antwort akzeptieren, weil ich es unter mysql mit Erfolg getestet habe. –

Verwandte Themen