Какой будет мой SQL-оператор, чтобы вставить "Арнольд Шварценеггер" и "Hasta la vista baby" в эти две пустые SQL-таблицы?

Что бы я сказал, чтобы вставить "Арнольд Шварценеггер" и "Hasta la vista baby" в следующие пустые таблицы SQL?

Первоначально этот вопрос должен был звучать так: "Как вставить первые записи в таблицы SQL с двунаправленными ассоциациями и автоматически сгенерированным целым числом PK?" но я не был уверен, правильно ли я сформулировал это... В основном, у меня есть две таблицы Actors а также CatchPhrases,

Actors похоже:

  ActorId                  int             NOT NULL  PK (autogenerated by db)
  FavoriteCatchPhraseId    int             NOT NULL  FK
  Name                     varchar(200)    NOT NULL

CatchPhrases похоже:

  CatchPhraseId            int             NOT NULL  PK (autogenerated by db)
  ActorId                  int             NOT NULL  FK
  PhraseText               varchar(500)    NOT NULL

Таким образом, актеры могут иметь несколько фраз, но должны иметь хотя бы одну. Уловочная фраза связана с актером. В настоящее время нет данных ни в одной таблице.

4 ответа

Решение

Я бы смоделировал это по-другому, чтобы избежать двунаправленного отношения (что было бы трудно сделать). Просто добавьте столбец (IsFavorite) в таблицу CatchPhrases. Либо используйте ограничение или бизнес-правило в коде, чтобы ограничить количество фраз-уловок, отмеченных как избранные для каждого актера, одним.

Актеры:

ActorId                  int             NOT NULL  PK (autogenerated by db)
Name                     varchar(200)    NOT NULL

Схватывать фразы:

CatchPhraseId            int             NOT NULL  PK (autogenerated by db)
ActorId                  int             NOT NULL  FK
PhraseText               varchar(500)    NOT NULL
IsFavorite               bit             NOT NULL

Убедитесь, что у вас есть индекс ActorId для таблицы CatchPhrases, чтобы вы могли быстро найти фразы-ловушки актера.

В качестве альтернативы можно использовать объединяющую таблицу, что позволит нескольким субъектам иметь одинаковую ключевую фразу

Актеры:

ActorId                  int             NOT NULL PK (autogenerated by db)
Name                     varchar(200)    NOT NULL

ActorCatchPhrases

ActorId                  int             NOT NULL PK (FK to Actors)
CatchPhraseId            int             NOT NULL PK (FK to CatchPhrases)
IsFavorite               bit             NOT NULL

Схватывать фразы

PhraseId                 int             NOT NULL PK (autogenerated by db)  
PhraseText               varchar(500)    NOT NULL

Правило, а именно то, что родительская запись должна иметь хотя бы одну дочернюю запись, не может быть применено с декларативной ссылочной целостностью.

"Favorite" - это единственное число, и поэтому FavoriteCatchPhrase может быть просто атрибутом объекта Actor, то есть столбцом в таблице Actors. Вы можете хранить текст фразы. Но если вы хотите применить правило о том, что любимая фраза должна происходить из набора добросовестных фраз, фраз, которые были проверены и признаны действительно "броскими", а не просто не слишком запоминающимся высказыванием, тогда у вас будет таблица CatchPhrases, и вы можете иметь Actor.FavoriteCatchPhrase для сохранения идентификатора фразы и ссылочной таблицы CatchPhrases в качестве внешнего ключа, хотя несколько акторов могут использовать одну и ту же фразу-ловушку, если вы не добавите уникальный индекс в Actor.FavoriteCatchPhrase.

Я мог бы сделать это примерно так:


USE     tempdb
;
CREATE  TABLE
        dbo.Actors
        (
        ActorId         INTEGER IDENTITY PRIMARY KEY,
        Name            VARCHAR(200) NOT NULL UNIQUE
        )
;
CREATE  TABLE 
        dbo.CatchPhrases
        (
        CatchPhraseId   INTEGER IDENTITY UNIQUE,
        ActorId         INTEGER NOT NULL REFERENCES dbo.Actors,
        PhraseText      VARCHAR(500) NOT NULL,

        PRIMARY KEY (CatchPhraseId, ActorId)
        )
;
CREATE  TABLE 
        dbo.ActorFavouritePhrase
        (
        ActorId         INTEGER NOT NULL REFERENCES dbo.Actors,
        CatchPhraseId   INTEGER NOT NULL,

        FOREIGN KEY (CatchPhraseId, ActorId) 
            REFERENCES dbo.CatchPhrases (CatchPhraseId, ActorId),

        PRIMARY KEY (ActorId, CatchPhraseId),
        UNIQUE (CatchPhraseId, ActorId)
        )
GO
CREATE  INDEX [dbo.CatchPhrases ActorId]
ON      dbo.CatchPhrases (ActorId)
GO
DECLARE @ActorId    TABLE (Id INTEGER NOT NULL);
DECLARE @PhraseId   TABLE (Id INTEGER NOT NULL)
;
BEGIN   TRANSACTION
;
INSERT  dbo.Actors 
        (Name)
OUTPUT  inserted.ActorId
INTO    @ActorId (Id)
VALUES  ('Arnold Schwarzenegger')
;
DECLARE @AID INTEGER = (SELECT Id FROM @ActorId)
;
INSERT  dbo.CatchPhrases
        (ActorId, PhraseText)
OUTPUT  inserted.CatchPhraseId
INTO    @PhraseId (Id)
VALUES  (@AID, 'Hasta la vista, baby')
;
DECLARE @PID INTEGER = (SELECT Id FROM @PhraseId)
;
INSERT  dbo.ActorFavouritePhrase
        (ActorId, CatchPhraseId)
VALUES  (@AID, @PID)
;
COMMIT  TRANSACTION
GO
DROP    TABLE
        dbo.ActorFavouritePhrase,
        dbo.CatchPhrases,
        dbo.Actors
;

Я думаю, что вы можете сделать это в транзакции, используя "грязное чтение" ( чтение незафиксировано).

Но это не очень приятно, даже если это возможно.

Как предложил @tvanfosson, самым чистым способом было бы отключить FK на столбце ActorId таблицы CatchPhrases.

Сначала создайте фиктивную строку CatchPhrases (для вставки идентификатора), например:

0 - 0 - "Нет любимой фразы", ​​0

Затем, когда вы хотите вставить строку Actors, по умолчанию используется:

(личность) - 0 - "Арнольд Шварценеггер"

Затем установите для переменной значение @@, которое сгенерирует вставка Actors

Тогда броская фраза:

(личность) - (переменная) - 'Hasta la vista baby'

Затем установите для переменной значение @@, которое будет сгенерировано вставкой CatchPhrases, и используйте ее для обновления идентификатора ключевой фразы в строке актеров.

... фу, ты уверен, что этот дизайн правильный?

РЕДАКТИРОВАТЬ

Хорошо, если мы можем изменить дизайн...

Смотря на отношения, у Актеров может быть много Фразовых фраз, и у Фишек может быть много Актеров. Таким образом, существует конструкция "многие ко многим", которая обычно подвергается рефакторингу с использованием объекта ссылки (MSDN называет это таблицей соединений):

Actors   
  |
-----
| | |
ActorsCatchphrases
| | |
-----
  |
Catchphrases
  • У актеров есть имя и детали актера (без ссылок на броские фразы)
  • ActorsCatchphrases имеет ActorId и CatchphraseId и логическое значение того, является ли он фаворитом этого актера.
  • Catchphrases содержит детали броской фразы (без ссылки на актера)
Другие вопросы по тегам