没有int时有关int的SQL存储过程错误

时间:2019-05-14 19:16:28

标签: sql sql-server tsql stored-procedures types

在我的存储过程(插入存储过程)中,我有一个部分检查客户是否存在。当我给出一个存在的客户名称(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 个答案:

答案 0 :(得分:2)

  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 :(得分:1)

代码到达错误点的原因是因为检查现有客户的代码存在逻辑问题。您试图询问是否存在包含该客户名称的行。但是,因为您使用了COUNT(),所以您实际上要问的是是否存在包含该名称的客户数量计数的行。即使计数为0,也将始终有一行,因此EXISTS将始终为true。

IF not exists (
   SELECT name
   FROM customer
   WHERE @customer= name

将通过尝试选择一个字段而不是使用聚合函数来解决此问题。


此外,错误本身是由一些不良的编程实践引起的。具体来说,我是在谈论使用相同的变量来存储两条不同的信息,并且还没有在使用正确的数据类型来存储信息。

您已经使用@customer@hotel做了两次,它们都开始代表名称,但是您稍后尝试重用它们来代表ID。这很不好,因为将相同的东西用于两个目的很容易混淆,而且因为ID是数字,应该存储在int变量中。当然,当错误检查失败并且将不存在的客户名称传递到select @customer= customerid from customer where @customer= name时,它不会选择ID,因此@customer继续包含该名称。然后,您稍后尝试将其插入到“客户”列为int列的“预订”字段中,因此出现无法将varchar(即文本)值插入整数字段的错误。

按照惯例,我建议您

a)创建单独的整数变量来表示客户ID和酒店ID值。

b)明确声明INSERT语句中的列。 (如果您在目标表中添加或删除其他列,这将为您节省以后的时间,那么列的顺序或数目不对就不会有问题。这将减少代码维护,并增加可读性。) / p>

c)作为更广泛的建议,我建议您的存储过程实际上接受客户ID和酒店ID作为输入参数,而不是名称。总是存在名称更改的危险,或者甚至两个记录实际上可能具有相同的名称(例如,在英国文化中,拥有两个名为John Smith的客户也就不足为奇了),这意味着您可以选择错误的ID。我假设您的数据库前面有一个用户界面。用户界面中应该可以让用户选择一个客户(可能是从下拉列表或自动完成功能中选择),并且用户界面应该知道这与哪个客户ID有关。如果是新客户,则用户必须先创建新客户记录,然后再进行其余的预订过程。大多数专业开发的应用程序都遵循这种方法(从现有记录中进行选择)。因此,在用户选择或创建客户之后,会将生成的客户ID而不是名称提供给存储过程。这样,对于哪个客户进行预订绝对没有任何歧义。

答案 2 :(得分:-1)

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