sql-server - 如何解决这个存储过程问题?
问题描述
我在 SQL Server 2017 中创建了这个存储过程,显然它一开始可以工作,但突然就停止工作了。
这应该验证汽车是否已经进入停车场。如果没有,则在车辆表中创建行和在车辆支付表中创建行。如果不是这种情况,它只会在车辆支付表中创建行并将状态更新为(意味着它当前处于)。
--table names, fields and variables are in spanish
CREATE TABLE Estacionamiento.Vehiculo
(
id INT IDENTITY (1, 1) NOT NULL
CONSTRAINT PK_Vehiculo_Estacionamiento_id
PRIMARY KEY CLUSTERED (id),
tipoVehiculo INT NOT NULL,
placa NVARCHAR(8) NOT NULL UNIQUE,
CONSTRAINT CHK_Formato_Placa_Vehiculo
CHECK (placa LIKE '[A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9]'),
estado BIT NOT NULL
)
GO
--Crear la tabla PagoVehiculo
CREATE TABLE Estacionamiento.PagoVehiculo
(
id INT IDENTITY(1, 1) NOT NULL
CONSTRAINT PK_Vehiculo_PagoVehiculo_id
PRIMARY KEY CLUSTERED (id),
vehiculo INT NOT NULL,
fechaHoraEntrada DATETIME NOT NULL,
fechaHoraSalida DATETIME NOT NULL,
total DECIMAL NOT NULL
)
GO
--The problem is here
CREATE PROCEDURE SP_InsercionVehiculosEntradasSalidas
(@placa NVARCHAR(8),
@tipoVehiculo NVARCHAR(15))
AS
BEGIN TRY
DECLARE @placaVehiculo INT
DECLARE @horaEntrada DATETIME
DECLARE @horaSalida DATETIME
IF NOT EXISTS(SELECT * FROM Estacionamiento.Vehiculo WHERE placa = @placa AND tipoVehiculo = @tipoVehiculo)
BEGIN
INSERT INTO Estacionamiento.Vehiculo (placa, tipoVehiculo, estado)
VALUES (@placa, @tipoVehiculo, 1)
SET @placaVehiculo = (SELECT id FROM Estacionamiento.Vehiculo WHERE placa = @placa)
INSERT INTO Estacionamiento.PagoVehiculo (vehiculo, fechaHoraEntrada, fechaHoraSalida, total)
VALUES (@placaVehiculo, GETDATE(), GETDATE(), 0)
END
ELSE IF EXISTS(SELECT * FROM Estacionamiento.Vehiculo WHERE placa = @placa)
BEGIN
SET @placaVehiculo = (SELECT id FROM Estacionamiento.Vehiculo WHERE placa = @placa)
PRINT(@placaVehiculo)
IF (SELECT estado FROM Estacionamiento.Vehiculo WHERE placa = @placa) = 0
BEGIN
INSERT INTO Estacionamiento.PagoVehiculo (vehiculo, fechaHoraEntrada, fechaHoraSalida, total)
VALUES (@placaVehiculo, GETDATE(), GETDATE(), 0)
UPDATE Estacionamiento.Vehiculo
SET estado = 1
END
ELSE IF (SELECT estado FROM Estacionamiento.Vehiculo WHERE placa = @placa) = 1
BEGIN
UPDATE Estacionamiento.PagoVehiculo
SET fechaHoraSalida = GETDATE()
WHERE vehiculo = @placaVehiculo
AND id = (SELECT MAX(id) FROM Estacionamiento.PagoVehiculo)
SET @horaEntrada = (SELECT MAX(fechaHoraEntrada)
FROM Estacionamiento.PagoVehiculo
WHERE vehiculo = @placaVehiculo)
SET @horaSalida = (SELECT MAX(fechaHoraSalida)
FROM Estacionamiento.PagoVehiculo
WHERE vehiculo = @placaVehiculo)
UPDATE Estacionamiento.Vehiculo
SET estado = 0
UPDATE Estacionamiento.PagoVehiculo
SET total = dbo.Fctn_CalculoPagoVehiculo(@horaEntrada, @horaSalida, @tipoVehiculo)
WHERE vehiculo = @placaVehiculo
AND id = (SELECT MAX(id)
FROM Estacionamiento.PagoVehiculo)
END
END
END TRY
BEGIN CATCH
DECLARE @error INT
SET @error = @@ERROR
RETURN @error
END CATCH
GO
我期待在需要时验证、插入和更新。
解决方案
在阅读您的过程时,我注意到了一些事情:
在某些地方,您可以通过以下方式检查表中的独特汽车vehiculo
:
WHERE placa = @placa AND tipoVehiculo = @tipoVehiculo
和其他地方做的只是
WHERE placa = @placa
根据哪个为您提供独特的汽车,在您的代码中保持一致
当汽车插入时PagoVehiculo
,您将使用当前日期填充进入和退出日期。虽然技术上没有错误,但我希望退出日期在汽车退出之前为空。这将有助于数据的清晰度。
有很多地方可以检查select *
,可以代替select 1
,效果会更好
没有ELSE
声明捕捉意外情况并报告和发布。
有一次,您试图通过执行以下操作获取特定汽车的 pagoVehiculo 表的 id:
id = (SELECT MAX(id) FROM Estacionamiento.PagoVehiculo)
没有保证会检索到正确的汽车(特别是因为您可能有多个客户同时写入表。添加一个附加子句以确保您正在为正确的汽车提取数据。例如:
id = (SELECT MAX(id) FROM Estacionamiento.PagoVehiculo where vehiculo = @placaVehiculo)
就 proc 的情况而言,我的猜测是要么静默失败,要么没有落入 IF 或 ELSE IF 中,因此只是跳过了整个过程。我将按如下方式进行调试(在查看评论后:
- 在主 If 语句中添加和 ELSE 语句以捕获意外情况
- 在 IF 部分、ELSE If 和 ELSE 部分添加一个打印语句(类似
print ('in IF statement')
这样您就知道正在执行哪个分支(或者您可以只调试它,如果您熟悉 SQL Proc 调试) - 删除该
try catch
部分并查看是否有异常被捕获并且由于某种原因没有重新抛出。
哦,我刚刚看到,在表tipoVehiculo
中定义INT
,但是您在 proc 中传递了 NVARCHAR(15),这可能是您遇到问题的原因。
推荐阅读
- react-native - 将多个导航器嵌套在堆栈中还是切换导航器更好?
- r - 比较两个数据框并有条件地提取另一列的值
- tcl - 设置命令的使用
- django - 在 Django 中编辑动态选择字段
- javascript - Rails 6 - 在某些控制器操作中需要 JS 文件
- android - 你能帮我创建这个浮动操作按钮吗?
- python - 我正在尝试通过电子邮件将图像作为附件发送而不保存图像。我想直接发送变量
- python-3.x - .encode("utf-8") 似乎不支持我的表情符号?
- sql-server - 我想知道 SQL Server 上的分片方式
- python-3.x - 为什么将列表转换为字符串时会出错?