SQL: создание таблицы отношений с 2 различными auto_increment
У меня есть 2 таблицы, обе с собственными автоматически увеличиваемыми идентификаторами, которые, конечно, являются первичными ключами.
Когда я хочу создать третью таблицу, чтобы установить связь между этими двумя таблицами, у меня всегда возникает ошибка.
Первый касается того, что вы можете иметь только 1 автоматически увеличивающийся столбец, второй возникает, когда я удаляю оператор auto_increment из этих двух, поэтому sql не позволяет мне создавать их внешние ключи из-за сбоя при сопоставлении типов.
Есть ли способ, которым я могу создать реляционную таблицу, не теряя функции автоинкремента?
Другое возможное (но не предпочтительное) решение может заключаться в том, что в первой таблице есть другой первичный ключ, который является именем пользователя пользователя, а не оператором автоматического увеличения, конечно. Это неизбежно?
Заранее спасибо.
1 ответ
Концепции
Вы неправильно поняли некоторые основные понятия, и в результате возникают трудности. Сначала мы должны обратиться к понятиям, а не к проблеме, как вы ее воспринимаете, и, следовательно, ваша проблема исчезнет.
автоматически увеличенные идентификаторы, которые, конечно, являются первичными ключами.
Нет, они не. Это распространенное заблуждение. И проблемы гарантированно начнутся.
ID
Поле не может быть первичным ключом в английском или техническом или реляционном смыслах.
Конечно, в SQL вы можете объявить любое поле
PRIMARY KEY
, но это волшебным образом не превращает его в первичный ключ в английском, техническом или реляционном смысле. Вы можете назвать чихуахуа "Ротвейлер", но это не превращает его в Ротвейлера, оно остается чихуахуа. Как и любой язык, SQL просто выполняет команды, которые вы ему даете, он не понимаетPRIMARY KEY
чтобы означать что-то реляционное, он просто ударяет по уникальному индексу в столбце (или поле).Проблема в том, что вы объявили
ID
бытьPRIMARY KEY
вы думаете о нем как о первичном ключе и можете ожидать, что он обладает некоторыми качествами первичного ключа. За исключением уникальности значения ID, он не дает никаких преимуществ. У него нет ни одного из качеств Первичного Ключа или какого-либо Реляционного Ключа в этом отношении. Это не ключ к английскому, техническому или реляционному смыслу. Объявляя неключевой ключ ключом, вы только запутаетесь, и обнаружите, что что-то ужасно неправильно, только когда пользователь жалуется на дубликаты в таблице.
Реляционные таблицы должны иметь уникальностьстрок
PRIMARY KEY
наID
поле не обеспечивает уникальность строки. Следовательно, это не реляционная таблица, содержащая строки, и если это не так, то это файл, содержащий записи. Он не обладает ни целостностью, ни мощностью (на данном этапе вы будете знать только о мощности соединения), ни скоростью, которую имеет таблица в реляционной базе данных.
Выполните этот код(MS SQL 2008) и докажите это себе. Пожалуйста, не просто прочитайте это и поймите это, а затем продолжайте читать остальную часть этого Ответа,этот код должен быть выполнен перед дальнейшим чтением. Это имеет целебную ценность.
CREATE TABLE dumb_file (
id INT NOT NULL IDENTITY PRIMARY KEY,
name_first CHAR(30) NOT NULL,
name_last CHAR(30) NOT NULL
)
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
INSERT dumb_file VALUES ( "Mickey", "Mouse" ) -- succeeds, but not intended
SELECT * FROM dumb_file
Обратите внимание, что у вас есть повторяющиесястроки. Реляционные таблицы должны иметь уникальные строки. Еще одно доказательство того, что у вас нет реляционной таблицы или каких-либо ее качеств.
Обратите внимание, что в вашем отчете уникальным является толькоID
поле, о котором ни один пользователь не заботится, ни один пользователь не видит, потому что это не данные, это какая-то дополнительная ерунда, которую какой-то очень глупый "учитель" велел вам вставить в каждый файл. У вас есть уникальностьзаписи, но нет уникальности строк.
С точки зрения данных (реальные данные минус посторонние дополнения), данные name_last
а такжеname_first
может существовать без ID
поле. У человека есть имя и фамилия без удостоверения личности, отпечатанного на его лбу.
Второе, что вы используете, что вас смущает, этоAUTOINCREMENT.
Если вы внедряете систему хранения записей без реляционных возможностей, конечно, это полезно, вам не нужно кодировать приращение при вставке записей. Но если вы внедряете реляционную базу данных, она вообще не имеет смысла, потому что вы никогда не будете ее использовать. В SQL есть много функций, которые большинство людей никогда не используют.
Корректирующее действие
Итак, как вы обновляете, повышаете тот файл dumb_file, который содержит повторяющиеся строки, до реляционной таблицы, чтобы получить некоторые качества и преимущества реляционной таблицы? Есть три шага к этому.
Вы должны понимать ключи
- И поскольку мы перешли от файлов ISAM 1970-х годов кРеляционной модели, вам необходимо понимать Реляционные ключи. То есть, если вы хотите получить преимущества (целостность, мощность, скорость) реляционной базы данных.
Доктор Э. Ф. Куд в своемРМ заявил, что:
ключ состоит из данных
а также
строки в таблице должны быть уникальными
Ваш "ключ" не составлен из данных. Это какой-то дополнительный паразит, не связанный с данными, вызванный тем, что вы заразились болезнью своего "учителя". Признайте это как таковой и предоставьте себе все умственные способности, которые дал вам Бог (обратите внимание, что я не прошу вас думать изолированно, фрагментарно или абстрактно, все элементы в базе данных должны быть интегрированы друг с другом). Составьте реальный ключиз данных и только из данных. В этом случае есть только один возможный ключ:
(name_last, name_first).
Попробуйте этот код,объявите уникальное ограничение на данные:
CREATE TABLE dumb_table ( id INT NOT NULL IDENTITY PRIMARY KEY, name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT UK UNIQUE ( name_last, name_first ) ) INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT dumb_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT dumb_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM dumb_table
Теперь у нас естьуникальность строк. Это последовательность, которая происходит с большинством людей: они создают файл, который позволяет обманывать; они не понимают, почему в выпадающих списках появляются дупы; пользователь кричит; они настраивают файл и добавляют индекс, чтобы избежать дублирования; они идут к следующему исправлению ошибки. (Они могут делать это правильно или нет, это другая история.)
Второй уровень. Для мыслящих людей, которые думают не по чём-то. Поскольку теперь у нас есть уникальность строк, то, что во имя Небес, является целью
ID
поле, почему у нас это даже есть??? О, потому что чихуахуа зовут Ротти, и мы боимся его трогать.Заявление о том, что это
PRIMARY KEY
ложно, но остается, вызывая замешательство и ложные ожидания. Единственный подлинный ключ есть, это(name_last, name_fist),
и это альтернативный ключ на данный момент.Следовательно
ID
поле совершенно лишнее; и индекс поддерживает его; и так глупоAUTOINCREMENT
; и так ложное заявление о том, что этоPRIMARY KEY
; и любые ваши ожидания от него ложны.Поэтому убери лишнее
ID
поле. Попробуйте этот код:CREATE TABLE honest_table ( name_first CHAR(30) NOT NULL, name_last CHAR(30) NOT NULL CONSTRAINT PK PRIMARY KEY ( name_last, name_first ) ) INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- succeeds INSERT honest_table VALUES ( "Mickey", "Mouse" ) -- fails, as intended INSERT honest_table VALUES ( "Minnie", "Mouse" ) -- succeeds SELECT * FROM honest_table
Работает просто отлично, работает как задумано, без посторонних полей и индексов.
Пожалуйста, помните это и делайте это правильно, каждый раз.
Ложные Учителя
В эти последние времена, как и советовали, у нас их будет много. Обратите внимание, что "учителя", которые размножаютсяID
столбцы, в силу подробного свидетельства в этом посте, просто не понимаютреляционную модель или реляционные базы данных. Особенно те, кто пишет об этом книги.
Как доказано, они застряли в технологии ISAM до 1970 года. Это все, что они понимают, и это все, чему они могут научить. Они используют контейнер базы данных SQL для простоты доступа, восстановления, резервного копирования и т. Д., Но содержимое представляет собой чистую систему хранения записей без реляционной целостности, мощности или скорости. AFAIC, это серьезное мошенничество.
В дополнение кID
Поля, конечно, есть несколько пунктов, которые являются ключевыми понятиями Реляционного или нет, которые, взятые вместе, заставляют меня сделать такой серьезный вывод. Эти другие предметы выходят за рамки этого поста.
Одна конкретная пара идиотов в настоящее время совершает нападение на первую нормальную форму. Они принадлежат в убежище.
Ответ
Теперь для остальной части вашего вопроса.
Есть ли способ, которым я могу создать реляционную таблицу, не теряя функции автоинкремента?
Это противоречивое предложение. Я надеюсь, что вы поймете из моего объяснения, реляционные таблицыне нужныAUTOINCREMENT
"функции"; если файл имеетAUTOINCREMENT
Это не реляционная таблица.
AUTOINCREMENT
хорош только для одного: если и только если вы хотите создать электронную таблицу Excel в контейнере базы данных SQL, изобилуя полями с именемA,
B,
а также C,
через верхнюю часть и запишите числа вниз по левой стороне. В терминах базы данных это являетсярезультатом SELECT, сглаженного представления данных, которое не является источником данных, которое организовано (нормализовано).
Другое возможное (но не предпочтительное) решение может заключаться в том, что в первой таблице есть другой первичный ключ, который является именем пользователя пользователя, а не оператором автоматического увеличения, конечно.Это неизбежно?
В технической работе нам нет дела до предпочтений, потому что это субъективно, и оно постоянно меняется. Мы заботимся о технической корректности, потому что она объективна, и она не меняется.
Да, это неизбежно. Потому что это просто вопрос времени; количество ошибок; номер "не могу"; количество криков пользователя, пока вы не столкнетесь с фактами, преодолеете свои ложные заявления и поймете, что:
единственный способ убедиться, что пользовательские строки уникальны, что user_names уникальны, это объявить
UNIQUE
ограничение на этои избавиться от
user_id
или жеid
в пользовательском файлечто способствует
user_name
вPRIMARY KEY
Да, потому что вся ваша проблема с третьей таблицей, не случайно, затем устраняется.
Эта третья таблица является ассоциативной таблицей. Единственный требуемый ключ (первичный ключ) является составной частью двух родительских первичных ключей. Это обеспечивает уникальность строк, которые определяются их ключами, а не их IDs.
Я предупреждаю вас об этом, потому что те же "учителя", которые научили вас ошибкам в реализации ID
поля, научить ошибки реализации ID
поля в ассоциативной таблице, где, как и в обычной таблице, она является излишней, не имеет смысла, вводит дубликаты и вызывает путаницу. И это вдвойне избыточно, потому что два ключа, которые предоставляют, уже есть, глядя нам в лицо.
Поскольку они не понимают RM или реляционные термины, они называют ассоциативные таблицы таблицами "связи" или "сопоставления". Если у них есть ID
поле, они на самом деле, файлы.
Таблицы поиска
ID
Поля особенно глупы для таблиц поиска или справки. Большинство из них имеют распознаваемые коды, нет необходимости перечислять список кодов в них, потому что коды являются (должны быть) уникальными.
Кроме того, наличие кодов в дочерних таблицах как FKs - хорошая вещь: код гораздо более значим, и он часто сохраняет ненужное соединение:
SELECT ...
FROM child_table -- not the lookup table
WHERE gender_code = "M" -- FK in the child, PK in the lookup
вместо:
SELECT ...
FROM child_table
WHERE gender_id = 6 -- meaningless to the maintainer
или хуже:
SELECT ...
FROM child_table C -- that you are trying to determine
JOIN lookup_table L
ON C.gender_id = L.gender_id
WHERE L.gender_code = "M" -- meaningful, known
Обратите внимание, что этого нельзя избежать: вам нужна уникальность в поисковом коде и уникальность в описании. Это единственный метод предотвращения дублирования в каждом из двух столбцов:
CREATE TABLE gender (
gender_code CHAR(2) NOT NULL,
name CHAR(30) NOT NULL
CONSTRAINT PK
PRIMARY KEY ( gender_code )
CONSTRAINT AK
UNIQUE ( name )
)
Полный пример
Исходя из подробностей вашего вопроса, я подозреваю, что у вас есть проблемы с синтаксисом SQL и определениями FK, поэтому я приведу в качестве примера полное решение, которое вам нужно (поскольку вы не дали определения файла):
CREATE TABLE user ( -- Typical Identifying Table
user_name CHAR(16) NOT NULL, -- Short PK
name_first CHAR(30) NOT NULL, -- Alt Key.1
name_last CHAR(30) NOT NULL, -- Alt Key.2
birth_date DATE NOT NULL -- Alt Key.3
CONSTRAINT PK -- unique user_name
PRIMARY KEY ( user_name )
CONSTRAINT AK -- unique person identification
PRIMARY KEY ( name_last, name_first, birth_date )
)
CREATE TABLE sport ( -- Typical Lookup Table
sport_code CHAR(4) NOT NULL, -- PK Short code
name CHAR(30) NOT NULL -- AK
CONSTRAINT PK
PRIMARY KEY ( sport_code )
CONSTRAINT AK
PRIMARY KEY ( name )
)
CREATE TABLE user_sport ( -- Typical Associative Table
user_name CHAR(16) NOT NULL, -- PK.1, FK
sport_code CHAR(4) NOT NULL, -- PK.2, FK
start_date DATE NOT NULL
CONSTRAINT PK
PRIMARY KEY ( user_name, sport_code )
CONSTRAINT user_plays_sport_fk
FOREIGN KEY ( user_name )
REFERENCES user ( user_name )
CONSTRAINT sport_occupies_user_fk
FOREIGN KEY ( sport_code )
REFERENCES sport ( sport_code )
)
Там PRIMARY KEY
декларация честна, это первичный ключ; нет ID;
нет AUTOINCREMENT;
без дополнительных показателей; нет повторяющихся строк; нет ошибочных ожиданий; нет сопутствующих проблем.
Модель данных
Вот модель данных, чтобы пойти с определениями.
Если вы не привыкли к нотации, имейте в виду, что каждый маленький тик, метка и отметка, сплошные или пунктирные линии, квадрат против круглых углов, означает что-то очень специфическое. Обратитесь к нотации IDEF1X.
Одна картинка стоит тысячи слов; в этом случае стандартная картина жалобы стоит больше, чем это; плохой не стоит той бумаги, на которой он нарисован.
Пожалуйста, внимательно проверяйте глагольные фразы, они включают набор предикатов. Остальная часть предикатов может быть определена непосредственно из модели. Если это не ясно, пожалуйста, спросите.