2010-08-29 12 views
6

Ich poste diese Frage, die etwas eine Zusammenfassung meiner anderen question ist.einzigartiges Paar in einer "Freundschaft" -Datenbank

Ich habe zwei Datenbanken:
1) db_users.
2) db_friends.

Ich betone, dass sie in separaten Datenbanken auf verschiedenen Servern gespeichert sind und daher keine Fremdschlüssel verwendet werden können.

In ‚db_friends‘ ich die Tabelle ‚tbl_friends‘ haben, die die folgenden Spalten:
- ID_USER
- id_friend

Jetzt Wie kann ich sicherstellen, dass jedes Paar in dieser Tabelle eindeutig ist ('tbl_friends')?
Ich möchte das auf der Tabellenebene und nicht durch eine Abfrage durchführen.

Zum Beispiel das sind ungültige Zeilen:
1 bis 2
2 - 1

Ich würde dies hinzuzufügen unmöglich sein mag.

Zusätzlich - wie würde ich für alle Freunde des Benutzers seach 713 während er erwähnt werden könnte, auf einigen Freundschaft Reihen, in der zweiten Spalte (‚id_friend‘)?

Antwort

6

Sie werden wahrscheinlich nicht in der Lage sein, dies auf Datenbankebene zu tun - Ihr Anwendungscode wird dies tun müssen. Wenn Sie sicherstellen, dass Ihre tbl_friends Datensätze immer mit (lowId, highId) eingehen, löst ein typischer PK/Unique Index das doppelte Problem. In der Tat würde ich so weit gehen, die Spalten in deinen tbl_friends in (id_low, id_high) umzubenennen, nur um das zu verstärken.

Ihre Anfrage nichts mit Benutzer zu finden 713 dann so etwas wie

SELECT id_low AS friend FROM tbl_friends WHERE (id_high = ?) 
UNION ALL 
SELECT id_high AS friend FROM tbl_friends WHERE (id_low = ?) 

Für Effizienz wäre, dann würden Sie wahrscheinlich indizieren möchten sie vorwärts und rückwärts - das ist durch (ID_USER, id_friend) und (id_friend, id_user).

Wenn Sie müssen dies auf einer DB-Ebene tun, dann würde eine gespeicherte Prozedur, um Argumente zu tauschen (Low, High) vor dem Einfügen funktionieren würde.

1

Nun, eine einzigartige Einschränkung auf das Paar von Spalten wird Sie auf halbem Weg dorthin bringen. Ich denke, der einfachste Weg, um sicherzustellen, dass Sie nicht die umgekehrte Version bekommen, wäre eine Einschränkung hinzuzufügen, die dafür sorgt, dass id_user < id_friend. Sie müssen diese Reihenfolge zum Zeitpunkt des Einfügens ausgleichen, aber Sie erhalten die von Ihnen gewünschte Beschränkung der Datenbankebene, ohne Daten zu duplizieren oder fremde Schlüssel zu verwenden. Für die zweite Frage, um alle Freunde für ID = 1 zu finden, können Sie id_user, id_friend von tbl_friend where id_user = 1 oder id_friend = 1 und dann in Ihrem Client-Code alle 1's unabhängig von Spalte werfen.

3

Sie müssen einen Auslöser verwenden, um diese Geschäftsregel durchzusetzen.
Die beiden Spalten in tbl_friends der Primärschlüssel (einzige Einschränkung scheitern das) würde nur sicherstellen, dass es keine Duplikate des gleichen Satzes sein kann: 1, 2 kann nur einmal erscheinen, aber 2, 1 wäre gültig.

Wie würde ich nach allen Freunden des Benutzers 713 suchen, während er in einigen Freundschaftszeilen in der zweiten Spalte ('id_friend') erwähnt werden könnte?

WHERE 713 IN (id_user, id_friend) 

..oder einer UNION:

Sie könnten eine IN verwenden

JOIN (SELECT id_user AS user 
     FROM TBL_FRIENDS 
     UNION ALL 
     SELECT id_friend 
     FROM TBL_FRIENDS) x ON x.user = u.user 
+0

Danke für die Antwort:

Sie können auch einfach für Freunde von 713 abfragen! Welche der obigen Abfragen ist leistungsstärker? – Poni

+0

@Poni: Ich empfehle immer, den EXPLAIN-/Abfrageplan für Ihr eigenes System zu überprüfen, um zu sehen, welche am besten funktioniert. –

0

Eine Möglichkeit, es tun können, ist, die beiden Freunde auf zwei Zeilen zu speichern:

CREATE TABLE FriendPairs (
    pair_id INT NOT NULL, 
    friend_id INT NOT NULL, 
    PRIMARY KEY (pair_id, friend_id) 
); 

INSERT INTO FriendPairs (pair_id, friend_id) 
VALUES (1234, 317), (1234, 713); 

Sehen? Es spielt keine Rolle, in welcher Reihenfolge Sie sie einfügen, da beide Freunde in die Spalte friend_id gehen. So können Sie leicht Einzigartigkeit erzwingen.

SELECT f2.friend_id 
FROM FriendPairs AS f1 
JOIN FriendPairs AS f2 ON (f1.pair_id = f2.pair_id) 
WHERE f1.friend_id = 713 
+0

Vielen Dank, dass Sie sich die Zeit genommen haben, Bill zu beantworten - nun, das scheint viel zu viel Overhead zu beinhalten - sowohl von der Anzahl der Zeilen (doppelte Größe) als auch von dem Frageaspekt, wo ich JOIN und so was machen muss Setzen Sie besser eine Einschränkung (id_user Poni

+0

@Poni: Nein, das würde nicht helfen. Wenn Sie Paare wie (137,317) und (317,713) haben, kann der Benutzer 317 immer noch in der ersten oder zweiten Spalte landen, auch wenn Sie 'id_user

Verwandte Themen