Ошибка хранимой процедуры SQL о int, пока нет int - PullRequest
1 голос
/ 14 мая 2019

В моей хранимой процедуре (вставьте хранимую процедуру) у меня есть раздел, который проверяет, существует ли клиент. Когда я даю имя клиента (varchar), которое существует, нет ошибок, но когда я вставляю имя, которое не существует, это выдает мне эту ошибку:

Преобразование не удалось при преобразовании значения varchar 'Briggs Standih' к типу данных int.

Briggs Standih - несуществующий клиент в моей базе данных.

Понятия не имею, где может быть ошибка ... Вот моя процедура и выполнимый.

create PROCEDURE spNieuweReservering
( 
   @customer VARCHAR(255), 
   @date1 date,
   @date 2date,
   @hotel varchar(40),
   @count_person int ,
   @emplyeeidint,
   @roomidint

) 
AS 
BEGIN 
   DECLARE @bookdate date    
IF not exists (
   SELECT count(*)
   FROM customer
   WHERE @customer= name
   )   
   BEGIN 
    raiserror('Deze klant bestaat niet. Controleer de naam of maak een nieuwe klant aan.',16,1)
   END 

   select @customer= customerid
   from customer
   where @customer= name

   select @hotel = hotelid
   from hotel
   where @hotel = location

   SELECT @bookdate= GETDATE()
   FROM boeking 

   begin transaction
   INSERT INTO booking values (@bookdate, @count_person, null, @customer, @hotel, @employeeid)
   insert into roombooking values (@roomid, @date1, @date2, null, null)
IF @@ERROR <> 0
BEGIN
    rollback
    raiserror('Er is een fout opgetreden bij het toevoegen van de reservering. Controleer de input',16,1)
    return
END
END 
commit

exec spNieuweReservering 'Briggs Standih', '2019-08-10', '2019-08-15', 'Eindhoven', 1, 1, 1

Надеюсь, кто-то знает, что я делаю неправильно.

Ответы [ 3 ]

2 голосов
/ 14 мая 2019
  select @customer= customerid
  from customer
  where @customer= name

Это ваша ошибка, вы пытаетесь вставить int в @customer, который является varchar. У вас будет такая же ошибка с отелем

select @hotel = hotelid
from hotel
where @hotel = location

Я предлагаю объявить 2 другие переменные

DECLARE @hotelId, @customerId INT

И используя их для достижения вашего результата

1 голос
/ 15 мая 2019

Причина, по которой код доходит до того, что вы получаете ошибку, состоит в том, что ваш код для проверки существующего клиента имеет логическую проблему.Вы пытаетесь спросить, существует ли строка, содержащая имя этого клиента.Однако, поскольку вы использовали 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.(Это сохранит вас позже, если вы добавите или удалите другие столбцы в целевых таблицах, тогда у вас не будет проблем с неправильным порядком или числом столбцов. Это приведет к меньшему обслуживанию кода и повышению читабельности.)

в) В качестве более широкой рекомендации я предлагаю, чтобы ваша хранимая процедура фактически принимала идентификатор клиента и идентификатор отеля в качестве входных параметров вместо имени.Всегда существует опасность того, что имена изменятся, или даже что две записи могут фактически иметь одно и то же имя (например, в британской культуре совсем не удивительно иметь двух клиентов по имени Джон Смит), то есть вы можете выбрать неправильный идентификатор.Я предполагаю, что перед вашей базой данных есть пользовательский интерфейс.В пользовательском интерфейсе должна быть возможность выбрать пользователя - возможно, из раскрывающегося списка или автозаполнения, а пользовательский интерфейс должен знать, к какому идентификатору клиента это относится.Если это новый клиент, то пользователь должен сначала создать новую запись о клиенте, а затем продолжить процесс бронирования.Большинство профессионально разработанных приложений следуют этому подходу (в отношении выбора из существующих записей).Таким образом, после того, как пользователь выбирает или создает клиента, полученный идентификатор клиента затем присваивается хранимой процедуре, а не имени.Таким образом, абсолютно не останется места для какой-либо двусмысленности относительно того, какой клиент делает заказ.

0 голосов
/ 14 мая 2019
create PROCEDURE spNieuweReservering
( 
   @customer VARCHAR(255), 
   @date1 date,
   @date2 date,
   @hotel varchar(40),
   @count_person int ,
   @emplyeeid int,
   @roomid int

) 
AS 
BEGIN 
   DECLARE @bookdate date    
   SET NOCOUNT ON;
   begin transaction MainTrans
IF not exists (SELECT count(*)  FROM customer WHERE @customer= name ) BEGIN 
    raiserror('Deze klant bestaat niet. Controleer de naam of maak een nieuwe klant aan.',16,1)
END 
BEGIN
   select @customer= customerid
   from customer
   where @customer= name

   select @hotel = hotelid
   from hotel
   where @hotel = location

   SELECT @bookdate= GETDATE()
   FROM boeking 

   INSERT INTO booking values (@bookdate, @count_person, null, @customer, @hotel, @employeeid)
   insert into roombooking values (@roomid, @date1, @date2, null, null)
END
IF @@ERROR <> 0
BEGIN
    rollback TRANSACTION MainTrans
    raiserror('Er is een fout opgetreden bij het toevoegen van de reservering. Controleer de input',16,1)
    return
END
ELSE
          BEGIN
             COMMIT TRANSACTION MainTrans               
          END
END 
...