Laden...

Einschränkungen non-null, unique or foreign-key verletzt

Erstellt von Tweaky vor 10 Jahren Letzter Beitrag vor 10 Jahren 14.107 Views
T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren
Einschränkungen non-null, unique or foreign-key verletzt

Hi zusammen,

ich verwende folgendes Datenbanksystem: SQLite mit s3db file.
Die DB ist im Code mit .Net3.5 erstellt worden.

Bevor ich ggf. Ausschnitte aus dem Code bringe vielleicht mal die Frage zunächst allgemein:
Des öfteren hatte ich folgende Meldung:

Einschränkungen konnten nicht aktiviert werden. Mindestens eine Zeile enthält Werte die die Einschränkungen non-null, unique or foreign-key verletzen.

Wieso kann ich bei einem SELECT überhaupt eine dieser Einschränkungen verletzen?
Dachte das sind Einschränkungen beim schreibenden Zugriff.

Zudem, wenn ich an der Stelle, an der die Exception fliegt, das Query abgreife und in SQLite Administrator von Hand ausführe, klappt es.

Kann mir jemand zum besseren Verständnis helfen?

1.696 Beiträge seit 2006
vor 10 Jahren

Hallo,

verwendest du Dataset, wenn ja, vielleicht die Einschränkungen des Datasets mal prüfen.

Grüße

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Ich verwende DataTables


        DataTable dt = new DataTable();
        try
        {
            command.CommandText = sql;
            SQLiteDataReader reader = command.ExecuteReader();
            dt.Load(reader);
            reader.Close();
        }
        catch (Exception e)
        {
            Console.Write(sql);
            throw new Exception(e.Message);
        }
        return dt;

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Ich habe nun die Lösung:

Im dt.Rows[0] kann man einen RowError auslesen. Dieser besagt nun was wirklich faul ist.
In meinem Fall war es:

Die Spalte 'name' überschreitet das MaxLength-Limit.

Nur versteh ich es noch nicht.
Im SQLite Administrator kann ich mit selbem Query abfragen und sehe dort eben den abgeschnittenen Namen (da bei Eintragung zu lang).

Daher nochmal die Frage:
Warum ist das Problem beim SELECT und nicht beim INSERT?!

5.658 Beiträge seit 2006
vor 10 Jahren

Hi Tweaky,

vielelicht hilft dir Limits In SQLite.

Christian

Weeks of programming can save you hours of planning

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Danke,
zugegeben, ich habe das jetzt nur überflogen, aber ich glaube dort keine Antwort auf meine Frage zu finden.

Das Problem (zumindest nach dem RowError) scheint sich auf einen überlangen Wert für die Zelle "name" zu sein. Selbiges kann ich durch SQLite Administrator bestätigen, da dort der Inhalt nicht vollständig war.

Ich hatte den VARCHAR auf 100 gesetzt und nun erweitert, wodurch das Skript nun durchläuft. Aber warum der Fehler beim anschließenden SELECT passiert und nicht beim INSERT kann ich nicht nachvollziehen.

Zumal im SELECT Ergebnis (im Row.ItemArray) der gesamte Name drin steht und nicht der aus der Datenbank!? Also wurde hier beim INSERT wohl einfach kastriert und dann aber vorgehalten. Das DataSet der DataTable scheint dann die Limitierung des DB Feldes uz bekommen (VARCHAR100) aber nicht dessen abgefragten Inhalt, sonder den zuvor gecachten Wert der beim INSERT verwendet wurde. Deshalb kommt vermutlich der Fehler zu stande.

Stimmt das so? Und warum wird da was vorgehalten!?

F
10.010 Beiträge seit 2004
vor 10 Jahren

Dir ist klar das SQLite und .NET zwei verschiedene Sachen sind?

SQLite war bis V3 in keinster weise Typisiert. Es wurden alle Daten als string abgelegt und der lesende war dafür zuständig die Daten richtig zu interpretieren.
Auch Einschränkungen wie Stringlängen interessieren SQLite in keinster weise.
Das sind nur Richtwerte die der Zugreifende beachten sollte.

Und der zugreifende bei .NET ist in deinem Fall eben die DataTable und die liest eben das Schema und behachtet es.

Dein Code sieht übrigens genau so aus wie man ihn eigentlich nicht schreiben sollte.

  1. Globales Command und Globale Connection? [Artikel] Ressourcen schonen - Datenbanken richtig öffnen und schließen
  2. Sql String? [Artikelserie] SQL: Parameter von Befehlen

Und bitte nicht Grundlagen überfliegen, dann kommt sowas zustande.

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Ich hatte bisher Primär mit MySQL zu tun.

SQLite war bis V3 in keinster weise Typisiert. Es wurden alle Daten als string abgelegt und der lesende war dafür zuständig die Daten richtig zu interpretieren.
Auch Einschränkungen wie Stringlängen interessieren SQLite in keinster weise.
Das sind nur Richtwerte die der Zugreifende beachten sollte.

Das ist mir so nicht bewusst gewesen. Allerdings scheint doch jetzt die Typisierung vorhanden zu sein.
Dennoch die Frage: Warum beim SELECT erst?

Wurde denn beim INSERT die Limitierung auf VARCHAR(100) missachtet und der überlange Name geschrieben? Entsteht das Limit erst dadurch das die DB Typisierung dem Anfragenden (.Net DataTable) diese info gibt und dort dann der Fehler entsteht, dadurch das der überlange Name aus der DB in die DT geladen wird?

Dann scheint mir SQLite mehr Lite zu sein als ich dachte. Irgendwie wiederstebt mir es, dass ich etwas limitiere aber dann doch selbst drauf achten muss... Ich hätte gehofft, das es beim INSERT Abgeschnitten wird oder da eben zum Fehler führt.

T
67 Beiträge seit 2010
vor 10 Jahren

Dennoch die Frage: Warum beim SELECT erst?
Wurde denn beim INSERT die Limitierung auf VARCHAR(100) missachtet und der überlange Name geschrieben? Entsteht das Limit erst dadurch das die DB Typisierung dem Anfragenden (.Net DataTable) diese info gibt und dort dann der Fehler entsteht, dadurch das der überlange Name aus der DB in die DT geladen wird?

Ein einfacher Test ohne diesen überlangen Datensatz könnte dir deine Frage beantworten. Kommt man heutzutage nicht selbst auf solche einfachen Ideen? Das würde dir sofort zeigen ob dein Code soweit funktioniert.

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Ich weiß das mein Skript funktioniert und das es mir nicht die Frage beantwortet.
Der Punkt ist in einer Schleife und wird Hunderte male durchlaufen und erst bei dem Fall in dem der Name zu lang ist kommt es zum Fehler.

Allerdings eben beim anschließendem SELECT und nicht bereits beim INSERT.
Ich bin mir durchaus bewusst was ich tue, aber scheinbar nicht was technisch dahinter passiert, da es mir in meinem bisherigen Arbeiten mit MySQL so nie untergekommen ist.

Soll ich mich jetzt für meine Frage entschuldigen?

16.834 Beiträge seit 2008
vor 10 Jahren

Wenn Du das ganze via Constraint umsetzt musst Du beim INSERT bereits den Fehler bekommen (constraint failed); ich krieg ihn jedenfalls.
Von Feld-Limitierungen halte ich sowieso nicht so viel, da CONSTRAINTS sich leichter ändern lassen.

Ansonsten ist es "üblich", dass auch auf der Repository-Seite in der Anwendung eine Validierung der Daten durchgeführt wird und vorher gar kein Insert versucht wird; spart auch I/O-Traffic.
Ergo kannst Du hier bereits Filtern.

Warum der/die Entwickler SQLite so umgesetzt hat, wie es ist, kann Dir hier wahrscheinlich kaum einer beantworten.
Dass SQLite nicht perfekt ist, ist bekannt.

T
Tweaky Themenstarter:in
24 Beiträge seit 2010
vor 10 Jahren

Danke für den Tipp mit den Constaints, damit sollte das recht einfach abgedeckt sein.

Ob einfacher änderbar oder nicht, ich dachte bisher, die Limitierungen wie Varchar(100) etc. sind auch eine Grundlage für die interne Optimierung des DBMS.

Obwohl ich mich nun doch für eine Validierung im Code entschieden habe.
Verwende ohnehin selbst gebaute DBOs, die sich beim Speichern nun prüfen.
Damit ist dann auch gleich das IO Thema erledigt, wobei ich nicht denke das es sich hier irgendwie bemerkbar machen könnte.