#c# #asp.net #sql-server-2008 #foreign-keys #composite-primary-key
#c# #asp.net #sql-server-2008 #внешние ключи #составной первичный ключ
Вопрос:
Я работаю с SQL Server 2008 R2, C # и ASP.Net . У меня есть таблица, в которой есть составной первичный ключ, состоящий из номера запроса и количества раз, когда этот запрос появляется в таблице. Частота обращения вычисляется с помощью кода C #:
VTTTickets.InsertParameters[0].DefaultValue = VTTTTicketNoBox.Text;
string CommString = "SELECT COUNT(*) FROM [Tickets] WHERE [Ticket_No] = "
VTTTTicketNoBox.Text;
string ConnString = ConfigurationManager.ConnectionStrings[1].ConnectionString;
OdbcConnection Conn = new OdbcConnection(ConnString);
Conn.Open();
OdbcCommand FooCommand = newOdbcCommand(CommString,Conn);
int FooVal = Convert.ToInt32(FooCommand.ExecuteScalar()) 1;
VTTTickets.InsertParameters[1].DefaultValue = Convert.ToString(FooVal);
VTTTTicketNoBox.Text = "";
Conn.Close();
Ограничение моих таблиц / код etc
CONSTRAINT [PK_Tickets] PRIMARY KEY CLUSTERED
([Ticket_No] ASC, [Ticket_Sub_No] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [Unique_Ticket_No] UNIQUE NONCLUSTERED
([Ticket_No] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
) ON [PRIMARY]
GO
Причина ограничения уникальности заключается в том, что эта часть первичного составного ключа также является внешним ключом для двух других таблиц.
Ошибка, которую я продолжаю получать, заключается в том, что она кричит на меня за то, что в уникальном ограниченном столбце присутствуют повторяющиеся значения. Это может произойти, как только все перейдет из разработки в производство, поскольку запрос может быть отправлен повторно.
Есть ли какой-либо способ создать внешний ключ без ограничения уникального ключа? Если нет, то как мне обойти эту проблему?
Комментарии:
1. Вам не следует редактировать свой вопрос, чтобы задать совершенно другой вопрос: вместо этого опубликуйте его как новый вопрос.
Ответ №1:
Это одна из тех ситуаций, с которыми мы часто сталкиваемся в программировании. Технология_A не позволит мне выполнить операцию_b, но это должно быть! Затем, после того, как мы некоторое время бились головой о стену, мы сдаемся (или переходим к Stackoverflow). Мы делаем это, потому что не используем технологию так, как она была задумана (что нормально, так мы учимся!)
Проблема здесь в вашей схеме базы данных.
Вы пытаетесь сделать слишком много с одной таблицей. Вы не должны хранить заявки (где одна и та же заявка может существовать более одного раза) в той же таблице, в которой вы отслеживаете количество вхождений.
На мой взгляд, есть две хорошие стратегии для исправления этой ситуации. Сначала я бы создал таблицу tickets с первичным ключом из одного столбца. Затем я бы создал таблицу, в которой хранится каждый экземпляр ticket.
Пример: Ticket43 закрыт, но снова открыт и закрыт снова. Это означает (если я правильно прочитал ваш вопрос), что у заявки было два экземпляра. Это означает, что в вашей исходной таблице будет две записи, но в моей новой предлагаемой схеме у нее будет одна запись в Tickets и две записи в Ticket_Instances.
Примечание: Вы захотите убедиться, что в Tickets хранится информация о билете, которая никогда не меняется между экземплярами, и информация о билете для конкретного экземпляра в Ticket_Instances.
Чтобы записать количество обращений, первое, что я бы сделал, это просто написать представление или фрагмент SQL, подобный следующему:
SELECT
count(*) as TicketCount,
TicketID
FROM
Ticket_Instances as TI
GROUP BY
TicketID
Если вы не хотите вычислять это по требованию, тогда я предлагаю использовать:
- ASP.NET Кэш (Запустите приведенный выше SQL, поместите его в кэш с интервалом времени в 10 минут)
- Используйте таблицу Ticket_Counts, которая заполняется триггером
Я подозреваю, что вы предпочтете вариант 2 там (хотя я бы использовал вариант 1).
Метод запуска:
Предполагая, что Ticket_Instances никогда не могут быть удалены, вам нужен только триггер Insert. Вы бы создали триггер в таблице Ticket_Instances при вставке, и этот триггер SQL выполнял бы следующее:
- Если TicketID не существует в Ticket_Counts, затем вставьте TicketID в Ticket_Counts с TicketCount равным 0
- Затем увеличьте TicketCount на 1 от TicketID в Ticket_Counts
С помощью этого метода вам нужно только получить доступ к Ticket_Counts по TicketID, чтобы получить # вхождений этого конкретного билета.
Я думаю, вы обнаружите, что ваши ошибки ограничения исчезнут, как только вы обновите свою схему.
Комментарии:
1. Спасибо за помощь. Я не совсем следовал предложению. Вместо этого я использовал таблицу-разделитель, чтобы обойти это. Таблица Tickets отправляет свой составной первичный ключ в промежуточную таблицу, которая отправляет только то, что мне нужно, в две другие таблицы в качестве внешних ключей. Это просто означает, что промежуточную таблицу нужно будет обновить номерами билетов, вот и все, и это нормально, потому что это работает.
2. Рад, что у вас все заработало. Существует несколько способов достижения этой цели, но иногда легко втянуться в выполнение с одной таблицей большего, чем они могут эффективно обработать. Удачи