在我的存储过程(插入存储过程)中,我有一个部分检查客户是否存在。当我给出一个存在的客户名称(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
希望有人确实知道我在做错什么。
答案 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