Einzigartigkeit von Priorisierungen von Einträgen in Tabellen sicherstellen

Ich hoffe ich befinde mich in der richtigen Rubrik…
Ich habe eine Tabelle die als Fremdschlüssel eindeutige IDs aus einer einer anderen Tabelle übernimmt. Zu jedem Fremdschlüssel gibt es mehrere Einträge - jedoch darf es nur einen ‘Haupteintrag’ zu jedem Fremdschlüssel geben.

ID  |  Eintrag
-----------------
1   |  a
1   |  b
1   |  C
1   |  d
2   |  A
2   |  b
2   |  c
3   |  A

Der großgeschriebene Eintrag soll den ‘Haupteintrag’ darstellen.
Ist es hier am sinnvollsten eine weitere Spalte vom Typ ‘binary’ hinzuzufügen und den Haupteintrag auf true zu setzen und mit einer RULE sicherzustellen, dass es pro ID immer nur einen Eintrag mit true gibt? Oder gibt es da bessere Alternativen?

Danke für Hinweise!



test=# create table s (id int, eintrag char);
CREATE TABLE
Time: 0,828 ms
test=*# create unique index idx_s on s(id) where eintrag=upper(eintrag);
CREATE INDEX
Time: 2,945 ms
test=*# insert into s values (1,'a');
INSERT 0 1
Time: 0,385 ms
test=*# insert into s values (1,'b');
INSERT 0 1
Time: 0,216 ms
test=*# insert into s values (1,'C');
INSERT 0 1
Time: 0,379 ms
test=*# insert into s values (1,'D');
ERROR:  duplicate key value violates unique constraint "idx_s"
DETAIL:  Key (id)=(1) already exists.

Hab ich Dich richtig verstanden?


Andreas

Hey Andreas,

im Grunde ja, nur das die Großschreibung der einzigartigen Einträge nur beispielhaft war. In der Tabelle stehen später ganze Wörter. Am Wort selbst ist aber nicht erkennbar ob es ein Haupt- oder nur ein Nebeneintrag ist.

Wie dann?

Andreas

Der erste hinzugefügte Eintrag für ein foreign key ist der Haupteintrag. Alle folgenden sollen Nebeneinträge werden. Daher meine Idee mit den RULES…

Datenbanken hantieren mit Mengen, von daher ist das etwas schlecht zu definieren. Was ist, wenn dieser Eintrag gelöscht wird?

Andreas

Wenn Du ein entsprechendes Flag zu der Tabelle dazu nimmst, dann geht es auch ohne RULES:

Wenn diese Spalte vom Typ boolean ist (“binary” gibt es bei Postgres nicht - keine Ahnung was Du damit gemeint hast), dann kannst Du das verwenden um einen entsprechenden Index anzulegen:

create unique index check_main on the_table (id) where is_main

is_main ist die neue Spalte vom Typ boolean. Wenn diese den Wert true hat, dann kann es die ID nur einmal geben. Ansonsten beliebig oft. Du must nur dafür sorgen, dass diese Spalte den korrekten Wert enhält.

Wenn dieser Eintrag mit dem boolean-flag (keine Ahnung was mich da mit binary trieb…) gelöscht würde wäre das allerdings schlecht. Vielleicht ist mein Ansatz auch viel zu kompliziert.
Ich suche eine einfache effiziente Methode für eine Suche von Büchern. Schwierig wird es durch den Umstand, dass es von einem Werk durchaus über 200 Ausgaben geben kann - das schließt fremdsprachige mit ein. Die habe ich in einen tsvector gepackt und den Autor gleich mit drangehangen.

textsearchable_index_gin = setweight(to_tsvector(e.title_lang, coalesce(e.title,'')), 'A') ||
setweight(to_tsvector('simple', coalesce(an.name,'')), 'B')

Da ich aber auch fremdsprachige Autorennamen finden lassen will hatte ich hier: http://www.pg-forum.de/allgemeines/5455-geschwindigkeit-der-suche.html schon mal nach der geeigneten Methode gefragt.
Ich habe mich nun dafür entschieden nur einen Namen in den tsvector zu packen, weil beim Hinzufügen einer anderen Schreibweise sonst sämtliche Ausgaben aller Bücher eines Autors geändert werden müssten was mal locker 30000 sein können und gin-updates ziemlich zäh verlaufen.
Um auch die anderen Schreibweisen zu finden wollte ich nun in der Suchanfrage ‘query rewriting’ benutzen und in meiner Autorentabelle eben jenen Haupteintrag des Autors rausfischen der zu dem eingegebenen passt. Sollte sich aber irgendwann rausstellen, dass der Haupteintrag falsch ist würde ich den loswerden wollen.
Wäre es da vielleicht sogar sinnvoller nicht den Autornamen in meinen tsvector zu schreiben sondern sogar nur die Autoren-ID? Dann wäre ich die Sache mit dem Haupteintrag los und würde lediglich vor der eigentichen Suche die ID per ‘query rewriting’ in die Suchanfrage einfügen. Oder macht man sowas erfahrungsgemäß nicht?

Du scheinst wesentlich mehr Probleme zu haben als nur diese Suche.
Vielleicht solltest du mal von vorne anfangen und grundsätzlich das Design überarbeiten.

Könntest du da etwas präziser sein?

Na, allein das Konzept, die Namen alle zusammen zu speichern, hört sich für mich fast unlösbar an.

Du meinst die Autorennamen? Da gibt es eine Tabelle für die Autoren deren primary keys dann als foreign keys in der Tabelle der Autorennamen dienen. Das läuft bei den Büchern und ihren Ausgaben ebenso. Inwiefern jetzt unlösbar?

Wenn das nicht unlösbar ist: was ist dann dein Problem?

Hab ich doch beschrieben ?? Was verstehst du an der Frage nicht? So richtig produktiv sind deine Kommentare nicht gerade… :frowning: Ich will dich wirklich nicht beleidigen - aber mir ist nicht ganz klar warum du in diesem Thread postest. Erklär es mir doch bitte.

Was dir bisher als Lösungen vorgeschlagen wurde, passt nicht so ganz zu deinem Problem.
Ich habe mir deine Postings mehrmals durchgelesen, verstehe aber nicht, was du da mit einer RULE erreichen möchtest.
Das ganze Konzept sieht für mich aber - auch Entschuldigung - unausgegoren aus.
Du hast angefangen mit Flags und Primärschlüsseln, später dann rückst du mit der Information heraus, das du da Namen von Autoren suchst und dort eigentlich dein Problem liegt.

Wie gesagt, vielleicht noch mal von vorne schauen, ob man das nicht anders - einfacher - anfangen könnte.

Hmm - du begnügst dich weiterhin mit Allgemeinplätzen, dass das was ich mache nicht gut ist. Das ist für mich wenig hilfreich solange du nicht konkreter darauf eingehst was nicht gut ist - geschweige denn dass du einen Vorschlag machst wie etwaige Fehler denn zu beheben wären.
Du schlägst vor noch mal von vorne anzufangen. Glaube mir, wenn ich das Problem so klar sehen würde wie du es anscheinend tust, dann würde ich selber bessere Vorschläge machen. Es gibt ja einen Grund warum ich hier nach Ideen frage…

Also - warum meintest du “Na, allein das Konzept, die Namen alle zusammen zu speichern, hört sich für mich fast unlösbar an.” Worauf wolltest du mich hinweisen? Ich kann deine Gedanken leider nicht lesen - insbesondere über eine so weite Entfernung.
Ich fand die Idee mit den Flags durchaus brauchbar um bestimmte Autorennamen zu markieren. Warum meinst du das Konzept wäre so nicht besonders gut?

Danke im Voraus für hilfreiche Antworten.

Wir drehen uns hier im Kreis. Du willst dein Konzept weiter verfolgen - gut.
Allerdings rückst du hier nur bei Bedarf mit deinen Problemen heraus und keiner von uns weiss, was bei dir noch alles auf dem Tisch liegt.
Dein aktuelles Problem ist ansonsten hoffentlich nur dein einziges Problem und alles andere funktioniert bereits perfekt.

Ok, lassen wir das also und wenden uns deinem aktuellen Problem zu:
Die Idee mit den Rules ist darum schon unbrauchbar, weil eine Rule zum Planer-Zeitpunkt evaluiert wird.
Du könntest also einen Trigger schreiben, der das erledigt - oder einen Exclusion Constraint (neu in PostgreSQL 9.0).
Das würde zumindest dein aktuelles Problem mit der Zuordnung lösen.

Da weiss ich aber noch nicht, ob das dein Problem mit der Volltextsuche auch erledigt.

Nein, ich bin für Änderungen offen - nur müssten diese schon benannt werden. Woher soll ich sonst wissen was zu ändern ist? Du hälst dich ja auch weiterhin mit den Problemen, die du sagst zu sehen sehr bedeckt.

Das ist denke ich auch ganz natürlich. Ich kann kaum verlangen, dass jemand sich durch mein komplettes Konzept arbeitet, um ein Problem am Rande zu begutachten. Ich kann aber gerne mehr dazu schreiben - was wäre denn von Interesse?

Wie kommst du auf sowas? Nein, es hakt hier und da und ich ändere des öfteren an dieser und jener Ecke. Und ich bin dankbar für Hilfe.

Ob Flag oder Trigger, beides sollte wohl funktionieren. Die Rule ist hiermit abgehakt. Danke für den Hinweis.
Hast du einen Gedanken zu der Volltextsuche? Ich will nicht ausschließen, dass ich mich nicht sehr genau ausgedrückt habe oder mein Ansatz unkoventionell ist. Das liegt aber lediglich daran, dass ich nicht weiß was konventionell ist :wink:

Wenn du eine Lösung für ein ganz konkretes Problem suchst, reicht eine Beschreibung genau dieses Problems.

Wenn du einen Ansatzpunkt für eine Verbesserung suchst, musst du schon etwas weiter ausholen und dazu schreiben, was du bereits hast, was du erreichen möchtest und wie du dir das derzeit vorstellst. Da reicht es nicht aus, einfach einen Ausschnitt mit dem Problem hier zu skizzieren.

Ich glaube, niemand hat etwas dagegen, dir hier zu helfen - aber das braucht schon ein paar weitere Informationen.

Ich hatte gehofft das bereits getan zu haben. Ich werde es also nocheinmal versuchen:

Ich habe eine Tabelle mit Buchtiteln in mehreren Sprachen und eine mit Autoren in mehreren Sprachen.
Ziel ist eine Volltextsuche in der jeder Buchtitel in Kombination des Autors (egal in welcher Sprache) gefunden werden kann. Hintergrund für diesen zunächst unsinnig erscheinden Wunsch ist, dass auch ein serbischer Benutzer das Buch 1984 von Orwell unter den Suchbegriffen 'Hiljadu devetsto osamdesetčetvrta’ und 'Orwell’ findet, obwohl der Herr sich auf serbisch eigentlich ‘Orvel’ schreibt - die sonst viel weiter verbreitete lateinische Schreibweise ‘Orwell’ aber dem Nutzer unter Umständen lediglich bekannt ist. Man möchte gar nicht glauben wie viele eigentich lateinische Namen in andere lateinische Schriftsysteme transkribiert werden.
Nun könnte man ja einfach alle unterschiedlichen lateinischen Namen an den für die Suche erstellten und bereits den Buchtitel enthaltenen tsvector anhängen - jedoch würde das meinen Suchindex erheblich vergrößern und dies würde sich vermutlich auf die Suchgeschwindigkeit niederschlagen. (Was nicht gewünscht ist!)

Daher hatte ich die Idee ‘query rewriting’ zu nutzen und nur den ersten in der Datenbank enthaltenen Namen in den Suchindex aufzunehmen. Vor der eigentlichen Suche würden alle möglichen Namensvarianten des Autors durch eben jenen Haupteintrag in der Sucheanfrage ersetzt. In vorangegangenen Beispiel und mit ‘Orwell’ als Haupteintrag würde also der Suchanfrage 'Hiljadu devetsto osamdesetčetvrta Orwell oder auch aus 'Hiljadu devetsto osamdesetčetvrta Orvel die Suchanfrage 'Hiljadu devetsto osamdesetčetvrta Orwell.
Um nun den Suchindex zu füllen wollte ich den jeweils ersten Eintrag eines Autorennames markieren. Dies ist sicher möglich, jedoch erschien mir eine andere Lösung einfacher:

Indem ich nicht einen wirklichen Namen in den Suchindex einfüge, sondern lediglich die Autoren-ID (z.B. Hiljadu devetsto osamdesetčetvrta autorenid_815 wenn Orwell die ID 815 hat) erspare ich mir den Haupteintrag, Flag oder Trigger und die Problematik was machen wenn eben jener Haupteintrag geändert werden müsste.

Dazu hätte ich gerne den Kommentar von Personen die sich mit Volltextsuchen ein wenig auskennen.