2013-07-17 2 views
1

У меня возникли проблемы с созданием таблицы в MySQL. По сути, мне нужен составной ключ, используя «client_id» и «problem_id». В таблице «клиенты» «client_id» является основным ключом, поэтому я хочу сохранить это отношение, а «problem_id» нужно автоматически увеличивать.Композитный ключ - один внешний ключ, другой автоинкремент

CREATE TABLE problems (
client_id BIGINT(10) NOT NULL REFERENCES clients(client_id), 
problem_id INT NOT NULL AUTO_INCREMENT, 
status CHAR(1) NOT NULL, 
description VARCHAR(100) NOT NULL, 
start_date VARCHAR(10) NOT NULL, 
end_date VARCHAR(10), 
PRIMARY KEY (client_id, problem_id) 
); 

MySQL не принимает это, но это кажется логичным для меня. Как я могу достичь такой таблицы?

+0

Вы обязаны использовать InnoDB? – Strawberry

ответ

3

Две проблемы:

  • InnoDB требует, чтобы столбец AUTO_INCREMENT будет первый столбец в основной ключ.

  • InnoDB не поддерживает синтаксис уровня столбца REFERENCES, он поддерживает только синтаксис ограничений на уровне таблицы FOREIGN KEY.

Это должно работать:

CREATE TABLE problems (
client_id BIGINT(10) NOT NULL, 
problem_id INT NOT NULL AUTO_INCREMENT, 
status CHAR(1) NOT NULL, 
description VARCHAR(100) NOT NULL, 
start_date VARCHAR(10) NOT NULL, 
end_date VARCHAR(10), 
PRIMARY KEY (problem_id, client_id), 
FOREIGN KEY (client_id) REFERENCES clients(client_id) 
); 

Однако, это означает, что ваш кластерный индекс (первичный ключ) пойдет на пользу поиски по problem_id, но не Lookups по client_id.

+0

Да - сообщение об ошибке кажется несколько обманчивым в этом отношении!«ОШИБКА 1075 (42000): неверное определение таблицы, может быть только один автоматический столбец, и он должен быть определен как ключ" – Strawberry

0

Я подозреваю, что вы должны сделать problem_id основным (кластеризационным) ключом и создать еще один индекс на client_id. MySQL включает ссылку на первичный ключ как часть других индексов.

CREATE TABLE problem (
    problem_id INT NOT NULL AUTO_INCREMENT, 
    client_id BIGINT(10) NOT NULL REFERENCES clients(client_id), 
    status CHAR(1) NOT NULL, 
    description VARCHAR(100) NOT NULL, 
    start_date DATE NOT NULL, 
    end_date DATE, 
    PRIMARY KEY (problem_id) 
    INDEX problem_ndx1 (client_id) 
); 
+0

Problem_id все равно может быть использован в предложениях WHERE и т. Д., А client_id недостаточно, чтобы однозначно идентифицировать строки. Будет ли это работать? – Amoeba

+0

@Amoeba: Предложение WHERE с client_id, problem_id (в этом порядке) будет использовать индекс problem_ndx1, который я определил, чтобы вернуть одну строку. Предложение WHERE с помощью client_id возвращает все строки проблем. Если порядок важен, добавьте start_date в индекс problem_ndx1. –

+0

Я раньше не использовал индексы. Итак, единственная строка проблем по-прежнему однозначно идентифицируется комбинацией problem_id и client_id? – Amoeba

1

Согласно AUTO INCREMENT docs, вы можете использовать только столбец автоинкрементируемого в составном ключе, если вы используете MyISAM или двигатели BDB:

Для MyISAM и BDB таблиц, может указывать AUTO_INCREMENT на вторичном столбце в индексе с несколькими столбцами.

Если вы используете InnoDB, это по-видимому, не допускается. Я бы предложил использовать только problem_id в качестве первичного ключа - он уникален сам по себе, и я не вижу никакой пользы в объединении его с client_id.

+0

У одного клиента может быть много проблем, поэтому мне нужно также выявить проблемы. – Amoeba

+0

Вы все равно должны быть в порядке с единственным 'problem_id' в качестве первичного ключа. Просто создайте «обычный» индекс в столбце «client_id» (ответ Гилберта Ле Блана также предлагает это), и любой запрос на проблемы со стороны клиента должен быть супер-быстрым. –

Смежные вопросы