Jak tworzyć relacje w MySQL

97

Na zajęciach wszyscy „studiujemy” bazy danych i wszyscy korzystają z programu Access. Znudzony tym, próbuję robić to, co robi reszta klasy, ale za pomocą surowych poleceń SQL z MySQL zamiast używać Access.

Udało mi się stworzyć bazy danych i tabele, ale jak teraz utworzyć relację między dwiema tabelami?

Jeśli mam moje dwa stoły w ten sposób:

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id )
)

i

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
    PRIMARY KEY ( customer_id )
)

Jak utworzyć „relację” między dwiema tabelami? Chcę, aby do każdego konta został „przypisany” jeden identyfikator klienta (aby wskazać, kto jest jego właścicielem).

Josh Hunt
źródło
48
„ODMAWIAM studiowania Access, przestudiuję PRAWDZIWY silnik bazy danych: MySQL” To jest duch! Gratulacje = D
Metafaniel
2
Zwróć uwagę, że ograniczenia klucza obcego nie implementują relacji, ale implementują integralność. Skojarzenie między account_id i customer_id w tabeli kont implementuje relację między odpowiednimi jednostkami.
reaanb
1
„To jest duch!”, O ile jest to mysql z InnoDB, a nie MyISAM. Ponadto postgreqsl ma kilka interesujących funkcji w porównaniu z MySQL, którym warto się przyjrzeć.
jgmjgm

Odpowiedzi:

103

Jeśli tabele są innodb, możesz je utworzyć w ten sposób:

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id ), 
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 
) ENGINE=INNODB;

Musisz określić, że tabele są innodb, ponieważ silnik myisam nie obsługuje klucza obcego. Spójrz tutaj, aby uzyskać więcej informacji.

Eric Hogue
źródło
Widziałem w artykule, że nie ma potrzeby określania klauzuli ENGINE = InnoDB, jeśli InnoDB jest zdefiniowany jako domyślny silnik przechowywania, można sprawdzić za pomocą polecenia (mysql> SELECT @@ default_storage_engine;)
Arun
80

jak powiedział ehogue, umieść to w swojej TABELI TWORZENIA

FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 

alternatywnie, jeśli masz już utworzoną tabelę, użyj polecenia ALTER TABLE:

ALTER TABLE `accounts`
  ADD CONSTRAINT `FK_myKey` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`) ON DELETE CASCADE ON UPDATE CASCADE;

Dobrym sposobem na rozpoczęcie nauki tych poleceń jest użycie narzędzi MySQL GUI , które zapewniają bardziej „wizualny” interfejs do pracy z bazą danych. Prawdziwą korzyścią z tego (w porównaniu z metodą Access) jest to, że po zaprojektowaniu tabeli za pomocą interfejsu GUI, pokazuje on SQL, który będzie uruchamiany, a zatem możesz się z tego uczyć.

nickf
źródło
3
Twoja odpowiedź jest najlepszym rozwiązaniem
Omar
14
CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id )
)

and

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
)

How do I create a 'relationship' between the two tables? I want each account to be 'assigned' one customer_id (to indicate who owns it).

Musisz zadać sobie pytanie, czy jest to relacja 1 do 1, czy 1 z wielu. To znaczy, czy każde konto ma klienta i czy każdy klient ma konto. A może będą klienci bez kont. Twoje pytanie sugeruje to drugie.

Jeśli chcesz mieć ścisłą relację 1 do 1, po prostu połącz dwie tabele.

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
)

W drugim przypadku poprawnym sposobem utworzenia relacji między dwiema tabelami jest utworzenie tabeli relacji.

CREATE TABLE customersaccounts(
    customer_id INT NOT NULL,
    account_id INT NOT NULL,
    PRIMARY KEY (customer_id, account_id)
    FOREIGN KEY customer_id references customers (customer_id) on delete cascade,
    FOREIGN KEY account_id  references accounts  (account_id) on delete cascade
}

Następnie, jeśli masz identyfikator_klienta i chcesz uzyskać informacje o koncie, dołączasz do kont i kont klientów:

SELECT a.*
    FROM customersaccounts ca
        INNER JOIN accounts a ca.account_id=a.account_id
            AND ca.customer_id=mycustomerid;

Dzięki indeksowaniu będzie to niezwykle szybkie.

Możesz również stworzyć WIDOK, który daje efekt połączonej tabeli kont klientów, zachowując ich oddzielne

CREATE VIEW customeraccounts AS 
    SELECT a.*, c.* FROM customersaccounts ca
        INNER JOIN accounts a ON ca.account_id=a.account_id
        INNER JOIN customers c ON ca.customer_id=c.customer_id;
user3842431
źródło
1
Myślę, że ca.nie miałeś na myśli ac.(3 miejsca).
Widok eliptyczny
napisałeś PRIMARY KEY (customer_id, account_id)bez przecinka po nim
theonlygusti
11

Dodając do komentarza ehogue'a, powinieneś dopasować rozmiar klawiszy w obu tabelach. Zamiast

customer_id INT( 4 ) NOT NULL ,

Zrób to

customer_id INT( 10 ) NOT NULL ,

i upewnij się, że kolumna int w tabeli klientów to również int (10).

Zak
źródło
7

Niektóre silniki MySQL obsługują klucze obce. Na przykład InnoDB może ustanawiać ograniczenia na podstawie kluczy obcych. Jeśli spróbujesz usunąć wpis w jednej tabeli, który ma elementy zależne w innej, usuwanie nie powiedzie się.

Jeśli używasz typu tabeli w MySQL, takiego jak MyISAM, który nie obsługuje kluczy obcych, nie łączysz tabel nigdzie poza diagramami i zapytaniami.

Na przykład w zapytaniu łączysz dwie tabele w instrukcji select za pomocą sprzężenia:

SELECT a, b from table1 LEFT JOIN table2 USING (common_field);
Gary Richardson
źródło
2

Oto kilka zasobów, które pomogą rozpocząć: http://www.anchor.com.au/hosting/support/CreatingAQuickMySQLRelationalDatabase i http://code.tutsplus.com/articles/sql-for-beginners-part- 3-relacje-baz danych - net-8561

Jak mówili inni, użyj GUI - spróbuj pobrać i zainstalować Xampp (lub Wamp), który uruchamia oprogramowanie serwerowe (Apache i mySQL) na twoim komputerze. Następnie, gdy przejdziesz do // localhost w przeglądarce, wybierz PHPMyAdmin, aby wizualnie rozpocząć pracę z bazą danych mySQL. Jak wspomniano powyżej, wykorzystano innoDB, aby umożliwić tworzenie relacji zgodnie z życzeniem. Sprawia, że ​​łatwiej jest zobaczyć, co robisz z tabelami bazy danych. Pamiętaj tylko, aby po zakończeniu ZATRZYMAĆ usługi Apache i mySQL - mogą one otwierać porty, które mogą narazić Cię na włamania / złośliwe zagrożenia.

user3659515
źródło
Jeśli skonfigurujesz apache i mysql, aby obsługiwały tylko żądania lokalne, nie musisz ich zatrzymywać. Poza tym użytkownicy powinni mieć przynajmniej zainstalowaną zaporę programową, jeśli instalują tego rodzaju usługi. Mając to na uwadze, wiele routerów domowych ma wbudowaną zaporę ogniową, więc porty i tak nie powinny być otwarte, chyba że zostały otwarte przez osobę mającą dostęp do routera.
Chris,
1

Jedną z zasad, które musisz znać, jest to, że kolumna tabeli, do której chcesz się odwołać, musi mieć ten sam typ danych, co tabela odniesienia. 2 jeśli zdecydujesz się użyć mysql, musisz użyć InnoDB Engine, ponieważ zgodnie z Twoim pytaniem jest to silnik, który obsługuje to, co chcesz osiągnąć w mysql.

Poniżej znajduje się kod wypróbuj go, chociaż jako pierwsi odpowiedzieli na to pytanie w 100% udzielili świetnych odpowiedzi i prosimy o rozważenie ich wszystkich.

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY (account_id)
)ENGINE=InnoDB;

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
     PRIMARY KEY ( account_id ), 
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 
)ENGINE=InnoDB; 
Musa
źródło
0
create table departement(
    dep_id      int primary key auto_increment,
    dep_name    varchar(100) not null,
    dep_descriptin      text,
    dep_photo       varchar(100) not null,
    dep_video       varchar(300) not null
);

create table newsfeeds(
    news_id         int primary key auto_increment,
    news_title      varchar(200) not null,
    news_description    text,
    news_photo          varchar(300) ,
    news_date           varchar(30) not null,
    news_video          varchar(300),
    news_comment        varchar(200),
    news_departement    int foreign key(dep_id) references departement(dep_id)
);
Anayat
źródło
Podaj wyjaśnienie podanego schematu.
samabcde