Как отметил в комментарии Дин Хардинг «Кодека», было бы полезно узнать, как вы вызываете хранимый процесс. Но вот несколько общих предложений.
Во-первых, общепринятым соглашением для хранимых процедур является возврат 0 в случае успеха и ненулевого значения в случае ошибки (вы можете использовать выходной параметр для кодов ошибок, но он является избыточным).
Во-вторых, прежде чем пытаться вставить значение, вы должны проверить, существует ли оно уже. Например. вот некоторый псевдокод:
if exists (select 1 from StudentApplication where Student_ID = @Student_ID)
begin
raiserror('Student ID already exists.', 16, 1)
return 1 -- Your caller would need to know that 1 identifies existing record
end
Обратите внимание, что в этом примере код T-SQL завершается после вызова raiserror, поэтому вам нужно обрабатывать это как исключение, если вы вызываете хранимый процесс из C # / VB.NET / etc. В качестве альтернативы вы можете опустить вызов raiserror и просто сохранить сохраненный процесс, возвращающий ожидаемый (клиентом) код ошибки.
Тогда есть небольшая вероятность того, что дубликат будет вставлен, но я думаю, что это приведет к фатальной ошибке, которую вам нужно будет обработать в клиентском коде (обработка ошибок зависит от клиента; в C # вы вероятно, получит SqlException, который вы можете запросить для конкретного кода).
Другой вариант - поместить транзакцию вокруг кода, который проверяет существующую запись, а затем вставляет новую.
Если вы хотите обработать ошибку в C #, вам нужно позаботиться о двух вещах. Сначала проверьте код возврата и обработайте ненулевые значения соответственно (клиент C # и хранимый процесс должны согласовать значение каждого кода ошибки). Затем вам также нужно обработать SqlExceptions . Свойства State и Number объекта SqlException могут помочь вам определить проблему. Имейте в виду, что для сообщений об ошибках, определенных на лету (как в моем примере), Number всегда будет возвращать 50 000 (я думаю).