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

Что бы я сказал, чтобы вставить «Арнольд Шварценеггер» и «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 ]

5 голосов
/ 05 марта 2011

Я бы смоделировал это иначе, чтобы избежать двунаправленного отношения (что было бы трудно сделать). Просто добавьте столбец (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
2 голосов
/ 05 марта 2011

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

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

1 голос
/ 05 марта 2011

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


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
;
1 голос
/ 05 марта 2011

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

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

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

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

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

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

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

Затем установите переменную в значение @@ identity, которое сгенерирует вставка Actors

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

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

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

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

EDIT

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

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

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