2010-08-29 4 views
3

lu le tutoriel How to handle a Many-to-Many relationship with PHP and MySQL.mysql plusieurs à plusieurs

Dans cette question, je me réfère à la section "schéma de base de données", qui énonce les règles suivantes:

Cette nouvelle table doit être construit à sur les résultats suivants:

* It must have a column which links back to table 'A'. 
* It must have a column which links back to table 'B'. 
* It must allow no more than one row to exist for any combination of rows from table 'A' and table 'B'. 
* It must have a primary key. 

maintenant c'est clair comme du cristal jusqu'à maintenant.

Le seul problème que j'ai est avec la règle 3ème ("Il doit permettre pas plus d'une ligne pour exister pour toute combinaison").
Je veux que cela s'applique également, mais cela ne semble pas fonctionner de cette façon. Je suis en mesure d'ajouter deux lignes qui reflètent la même relation

Sur mon exemple de test de MySQL (5.XX)!

Par exemple, si je fais cette relation (en ajoutant une ligne):
A à B
Il me permet aussi de faire cette relation ainsi:
B à A

la question est en fait deux questions:

1) Comment puis-je la 3ème règle qui ne permettra pas de faire ce qui précède? Avoir une seule relation unique quelle que soit la combinaison.

2) Quand je veux recherche de tous les rapports de « A », à quoi ressemblerait la requête SQL comme?

Note # 1: Au fond de mon objectif final est de créer un système « d'amitié », et pour autant que je comprends la solution est un nombre à plusieurs table. Suggérez autrement si possible.

Note n ° 2: La table des utilisateurs est sur une autre base de données des relations (appeler amitiés) Table. Par conséquent, je ne peux pas utiliser de clés étrangères.

+0

J'ai posté une "clarification" question ici: http://stackoverflow.com/questions/3597078 – Poni

Répondre

2

Pour la première question:

  1. Créer une contrainte unique sur les deux colonnes
  2. Assurez-vous toujours ordonner les colonnes.Donc, si votre table a les colummns a et b que vous assurer que a est inférieur ou égal à b

Pour la deuxième question:

SELECT 
    * 
FROM 
    many_to_many_table 
WHERE 
    a = A or b = A 
+0

"contrainte unique"? Désolé mais je ne parle pas SQLish (: Pourriez-vous m'expliquer?) Je connais les clés étrangères - si c'est ce que vous vouliez dire non, je ne peux pas le faire parce que les ID proviennent d'une base de données complètement différente. En ce qui concerne la clause # 2 - je n'ai pas compris celle-ci aussi, seule la réponse à la deuxième question est comprise, je vous remercie pour le patient et la bonne volonté, vraiment, merci – Poni

+0

@Poni: Vous pouvez soit créer une contrainte unique sur les deux colonnes ou une clé primaire sur les deux colonnes (jetez un oeil à l'exemple de statican pour cela) Voici les docs sur la façon de créer une contrainte unique: http://dev.mysql.com/doc/refman/5.1/fr/ innodb-foreign-key-constraints.html 'alter table many_to_many_table ajoute un index unique (a, b);' – Wolph

+0

Une clé primaire sur les deux colonnes rendrait une paire unique bien que l'autre combinaison de cette paire puisse être ajoutée, que je ne veux pas 1 <-> 2 & 2 <-> 1. Le second n'est pas voulu. – Poni

0

Ok Wolph était plus rapide, je essentiellement d'accord (notez que vous devez créer une contrainte simple sur les deux colonnes en même temps!). Et juste pour expliquer pourquoi vous entrez en collision avec les règles que vous avez mentionnées: Typiquement, A et B sont des tables différentes. Ainsi, l'exemple typique des relations n: m autoriserait les entrées (1, 0) et (1, 1), car elles feraient référence à des paires différentes. Avoir la table A = la table B est une situation différente (vous utilisez A et B comme utilisateurs, mais dans l'exemple ce sont des tables).

+0

nicolas merci pour le soutien - désolé si je ne vous comprends pas, ou WoLpH. Consultez notre commentaire sur sa réponse, j'apprécierais des mots plus informatifs! – Poni

1

Il semble que vous vouliez une clé primaire composite.

CREATE TABLE relationship (
    A_id INTEGER UNSIGNED NOT NULL, 
    B_id INTEGER UNSIGNED NOT NULL, 
    PRIMARY KEY (A_id, B_id) 
); 

Voici comment configurer une table afin qu'il ne peut jamais être une ligne qui définit les tables A et B comme connexes. Cela fonctionne car une clé primaire doit être unique dans une table. La base de données n'autorise donc qu'une seule ligne avec une paire de valeurs spécifique. Vous pouvez créer des clés composites qui ne sont pas une clé primaire et qui n'ont pas besoin d'être uniques (mais vous pouvez créer une clé non primaire unique, composite ou non), mais votre spécification a demandé une clé primaire, c'est ce que je suggéré.

Vous pouvez, bien sûr, ajouter d'autres colonnes pour stocker des informations sur cette relation spécifique.

+0

Merci d'avoir pris le temps de répondre à staticsan! Eh bien, le code que vous avez posté ne l'atteint pas, mais votre description est mon objectif. Comment ça se passe ça ne marche pas? Voici le code exact que j'utilise pour créer la table: CREATE TABLE SINON EXISTE 'db_relations'.'tbl_relations' ( ' id_a' INT UNSIGNED NOT NULL, 'id_b' INT UNSIGNED NOT NULL, clé primaire (' ID_A ',' id_b')) MOTEUR = InnoDB; – Poni

+0

J'ai supposé que vous avez deux différents types d'objets, une telle personne et une adresse postale, comme suggéré par votre description de «table A» et «table B». Cela signifie qu'une référence à la "table A" sera * toujours * dans "id_a" et une référence à la "table B" sera toujours dans "id_b", sinon cela n'aurait aucun sens. Ou être utile. – staticsan