Причина, по которой код доходит до того, что вы получаете ошибку, состоит в том, что ваш код для проверки существующего клиента имеет логическую проблему.Вы пытаетесь спросить, существует ли строка, содержащая имя этого клиента.Однако, поскольку вы использовали COUNT()
, на самом деле вы спрашиваете, существует ли строка, содержащая количество клиентов с таким именем.Даже если счетчик равен 0, всегда будет строка, поэтому EXISTS
всегда будет истинным.
IF not exists (
SELECT name
FROM customer
WHERE @customer= name
исправит это, пытаясь выбрать поле, а не использовать статистическую функцию.
Кроме того, сама ошибка происходит из-за плохой практики программирования.В частности, я говорю об использовании одной и той же переменной для хранения двух разных фрагментов информации, а также о неправильном использовании типов данных для хранения информации.
Вы сделали это дважды, с обоими @customer
и @hotel
- они оба начинают представлять имена, но позже вы попытаетесь использовать их для представления идентификатора.Это плохо, потому что сложно использовать одно и то же для двух целей, а также потому, что идентификаторы являются числами и должны храниться в int
переменных.И, конечно, когда проверка ошибок завершается неудачно и несуществующее имя клиента передается в select @customer= customerid from customer where @customer= name
, идентификатор не выбирается, поэтому @customer
продолжает содержать имя.Затем вы позже попытаетесь вставить это в поле резервирования, столбец которого является столбцом int
- отсюда ошибка, что вы не можете вставить значение varchar (т.е. текст) в целочисленное поле.
Как хорошая практикаЯ бы порекомендовал вам
a) создать отдельные целочисленные переменные для представления идентификатора клиента и значений идентификатора отеля.
b) явно указать столбцы в ваших операторах INSERT
.(Это сохранит вас позже, если вы добавите или удалите другие столбцы в целевых таблицах, тогда у вас не будет проблем с неправильным порядком или числом столбцов. Это приведет к меньшему обслуживанию кода и повышению читабельности.)
в) В качестве более широкой рекомендации я предлагаю, чтобы ваша хранимая процедура фактически принимала идентификатор клиента и идентификатор отеля в качестве входных параметров вместо имени.Всегда существует опасность того, что имена изменятся, или даже что две записи могут фактически иметь одно и то же имя (например, в британской культуре совсем не удивительно иметь двух клиентов по имени Джон Смит), то есть вы можете выбрать неправильный идентификатор.Я предполагаю, что перед вашей базой данных есть пользовательский интерфейс.В пользовательском интерфейсе должна быть возможность выбрать пользователя - возможно, из раскрывающегося списка или автозаполнения, а пользовательский интерфейс должен знать, к какому идентификатору клиента это относится.Если это новый клиент, то пользователь должен сначала создать новую запись о клиенте, а затем продолжить процесс бронирования.Большинство профессионально разработанных приложений следуют этому подходу (в отношении выбора из существующих записей).Таким образом, после того, как пользователь выбирает или создает клиента, полученный идентификатор клиента затем присваивается хранимой процедуре, а не имени.Таким образом, абсолютно не останется места для какой-либо двусмысленности относительно того, какой клиент делает заказ.