Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Дублирование первичных ключей  [new]
titans
Member

Откуда:
Сообщений: 73
Всем привет. Есть одна задачка, посоветовался с коллегами, так ещё больше запутался.
Есть две таблицы:
1) Variant
CREATE TABLE Variant
       (id     INTEGER      NOT NULL IDENTITY(1,1),
		id_var     INTEGER    CONSTRAINT var_prk PRIMARY KEY,
        variant      NVARCHAR(500)  NOT NULL , 
		right_answ 	BIT NOT NULL , 
		CONSTRAINT var_unq_nam UNIQUE (variant,right_answ)
		)
GO
insert into Variant (id_var, variant, right_answ) values (1,'да', 0)
insert into Variant (id_var, variant, right_answ) values (1,'нет',1)

2)Organizer
CREATE TABLE Organizer
       (id     INTEGER     NOT NULL IDENTITY(1,1) CONSTRAINT org_prk PRIMARY KEY,
        Name      VARCHAR(100)  NOT NULL ,
		id_quest      INTEGER      NOT NULL CONSTRAINT org_frk_org REFERENCES Question(id) ON DELETE CASCADE ,
		id_var     INTEGER      NOT NULL CONSTRAINT var_frk_org REFERENCES Variant(id_var) ON DELETE CASCADE ,
		Num_of_quest      INTEGER  NOT NULL ,		
		time_on_answ 	 Time   NOT NULL ,
        CONSTRAINT org_unq_nam UNIQUE (Name, id_quest, id_var,  Num_of_quest, time_on_answ))
		
go
insert into Organizer (name, id_quest, id_var, Num_of_quest, time_on_answ) values ('Тест SQL Junior Level', 1,1,1,'00:02:00')

Идея в следующем. Таблица Organizer содержит вопрос и неограниченное кол-во ответов.
Таблица Variant и содержит эти самые ответы. Когда мы добавляем запись в Organizer, мы пишем, вопрос id_quest =1 ответы id_var=1
И в таблице ответов мы их перечисляем. Ну например как я привел выше, ответ да и нет.right_answ это поле правильный ответ или нет. Я знаю, что таблица Variant не правильно написана. А именно при вставке данных пишет что такой ключ уже есть.Что мне делать?
25 янв 13, 21:21    [13830675]     Ответить | Цитировать Сообщить модератору
 Re: Дублирование первичных ключей  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
titans
Что мне делать?
Прочитать теорию реляционных баз данных, а конкретно про первичные и внешние ключи.
26 янв 13, 00:25    [13831476]     Ответить | Цитировать Сообщить модератору
 Re: Дублирование первичных ключей  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
titans
Всем привет. Есть одна задачка, посоветовался с коллегами, так ещё больше запутался.
+ описания таблиц

Есть две таблицы:
1) Variant
CREATE TABLE Variant
       (id     INTEGER      NOT NULL IDENTITY(1,1),
		id_var     INTEGER    CONSTRAINT var_prk PRIMARY KEY,
        variant      NVARCHAR(500)  NOT NULL , 
		right_answ 	BIT NOT NULL , 
		CONSTRAINT var_unq_nam UNIQUE (variant,right_answ)
		)
GO
insert into Variant (id_var, variant, right_answ) values (1,'да', 0)
insert into Variant (id_var, variant, right_answ) values (1,'нет',1)

2)Organizer
CREATE TABLE Organizer
       (id     INTEGER     NOT NULL IDENTITY(1,1) CONSTRAINT org_prk PRIMARY KEY,
        Name      VARCHAR(100)  NOT NULL ,
		id_quest      INTEGER      NOT NULL CONSTRAINT org_frk_org REFERENCES Question(id) ON DELETE CASCADE ,
		id_var     INTEGER      NOT NULL CONSTRAINT var_frk_org REFERENCES Variant(id_var) ON DELETE CASCADE ,
		Num_of_quest      INTEGER  NOT NULL ,		
		time_on_answ 	 Time   NOT NULL ,
        CONSTRAINT org_unq_nam UNIQUE (Name, id_quest, id_var,  Num_of_quest, time_on_answ))
		
go
insert into Organizer (name, id_quest, id_var, Num_of_quest, time_on_answ) values ('Тест SQL Junior Level', 1,1,1,'00:02:00')

Идея в следующем. Таблица Organizer содержит вопрос и неограниченное кол-во ответов.
Таблица Variant и содержит эти самые ответы. Когда мы добавляем запись в Organizer, мы пишем, вопрос id_quest =1 ответы id_var=1
И в таблице ответов мы их перечисляем. Ну например как я привел выше, ответ да и нет.right_answ это поле правильный ответ или нет. Я знаю, что таблица Variant не правильно написана. А именно при вставке данных пишет что такой ключ уже есть.Что мне делать?
На самом деле у вас 3 таблицы, а я бы предложил сделать 4:)

У вас есть:
список всех возможных вопросов
список всех возможных ответов с признаком "правильный/не правильный ответ" (без привязки к вопросам)
органайзер, определяющий, к какому вопросу относится тот или иной ответ

Сейчас проблема в том, что на разные вопросы возможны одинаковые ответы, и при вводе одного из вариантов ответа на вопрос вы обнаружили (а точнее, SQL-сервер по условию уникальности VAR_UNQ_NAM) , что такой ответ уже внесен в таблицу ответов (при вводе ответов на какой-то из предыдущих вопросов). Значит, перед добавлением варианта ответа необходимо предварительно убедиться в его отсутствии, или использовать id_var найденного варианта ответа (если он уже есть в таблице). Еще лучше ссылаться непосредственно на ID, как это и посоветовал Mind 13831476.

Следуя этому же совету, логичнее убрать признак "правильный ответ" из справочника вариантов ответов и оформить его в виде отдельной таблицы (№4) правильных ответов структуры (id identity, right_answer int references Variant(id)), со ссылкой на эту таблицу из таблицы вопросов. (Согласен, спорный момент: городить огород из-за одного бита, но давайте посмотрим, что из этого может получиться)

Схема добавления нового вопроса и вариантов ответа на него может быть следующей:
- добавляем новый вопрос в таблицу вопросов (получаем id нового вопроса, но пока не знаем id правильного ответа, отложим на потом)
- для каждого из вариантов ответа добавляем (или определяем id имеющегося) вариант ответа (получили id варианта ответа)
- в органайзер добавляем новую связку между id вопроса и id варианта ответа
- после добавления всех вариантов ответов (или в момент добавления правильного варианта) добавляем id правильного варианта в таблицу правильных ответов (и получаем id правильного ответа)
- выполняем отложенную на потом регистрацию ключа правильного ответа в таблице вопросов (имея id вопроса и id правильного ответа)

На этом ввод информации по новому вопросу завершен

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

PS все вышеизложенное относится к категории ЯТД:) Вполне можно обойтись и тремя таблицами (но я бы выбрал четыре, хотя бы потому, что мне это представляется более логичным, а так же из-за желания опробовать отсроченную регистрацию ключа. Возможно, я не прав:)
26 янв 13, 02:15    [13831857]     Ответить | Цитировать Сообщить модератору
 Re: Дублирование первичных ключей  [new]
titans
Member

Откуда:
Сообщений: 73
Спасибо за развернутый ответ. Я воспользуюсь вашей структурой из 4 таблиц. Я буду делать добавление через процедуры, так что проблем с поздней регистрацией не должно возникнуть. Ещё раз огромное спасибо!
28 янв 13, 16:08    [13840207]     Ответить | Цитировать Сообщить модератору
 Re: Дублирование первичных ключей  [new]
П-Л
Guest
автор
список всех возможных вопросов
список всех возможных ответов с признаком "правильный/не правильный ответ" (без привязки к вопросам)
органайзер, определяющий, к какому вопросу относится тот или иной ответ

Трудновато представить как это один и тот же ответ может относиться к нескольким вопросам. Когда я делал систему тестирования, то у меня были:
Таблица тестов (Тест)
Таблица вопросов по тестам (Вопрос, ссылка на Тест, Тип вопрос (только один, несколько, ...))
Таблица вариантов ответов к каждому вопросу (Вариант ответа, ссылка на Вопрос)
т.е. вы две мои таблицы разогнали до 4.
28 янв 13, 16:19    [13840303]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить