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, который содержит повторяющиеся строки, до реляционной таблицы, чтобы получить некоторые качества и преимущества реляционной таблицы? Есть три шага к этому.

  1. Вы должны понимать ключи

    • И поскольку мы перешли от файлов ISAM 1970-х годов кРеляционной модели, вам необходимо понимать Реляционные ключи. То есть, если вы хотите получить преимущества (целостность, мощность, скорость) реляционной базы данных.

    Доктор Э. Ф. Куд в своемРМ заявил, что:

    ключ состоит из данных

    а также

    строки в таблице должны быть уникальными

    Ваш "ключ" не составлен из данных. Это какой-то дополнительный паразит, не связанный с данными, вызванный тем, что вы заразились болезнью своего "учителя". Признайте это как таковой и предоставьте себе все умственные способности, которые дал вам Бог (обратите внимание, что я не прошу вас думать изолированно, фрагментарно или абстрактно, все элементы в базе данных должны быть интегрированы друг с другом). Составьте реальный ключиз данных и только из данных. В этом случае есть только один возможный ключ: (name_last, name_first).

  2. Попробуйте этот код,объявите уникальное ограничение на данные:

         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
    

    Теперь у нас естьуникальность строк. Это последовательность, которая происходит с большинством людей: они создают файл, который позволяет обманывать; они не понимают, почему в выпадающих списках появляются дупы; пользователь кричит; они настраивают файл и добавляют индекс, чтобы избежать дублирования; они идут к следующему исправлению ошибки. (Они могут делать это правильно или нет, это другая история.)

  3. Второй уровень. Для мыслящих людей, которые думают не по чём-то. Поскольку теперь у нас есть уникальность строк, то, что во имя Небес, является целью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.

  • Одна картинка стоит тысячи слов; в этом случае стандартная картина жалобы стоит больше, чем это; плохой не стоит той бумаги, на которой он нарисован.

  • Пожалуйста, внимательно проверяйте глагольные фразы, они включают набор предикатов. Остальная часть предикатов может быть определена непосредственно из модели. Если это не ясно, пожалуйста, спросите.

Другие вопросы по тегам