如何解决此存储过程问题?

时间:2019-07-15 01:42:45

标签: 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

我希望在需要时进行验证,插入和更新。

1 个答案:

答案 0 :(得分:0)

在阅读您的proc时,我需要注意的几件事:

在某些地方,您可以通过以下方法在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中,从而跳过了整个过程。我将如下调试(在查看评论之后:

  1. 在主If语句中添加和ELSE语句以捕获意外情况
  2. 在IF部分,ELSE If和ELSE部分中添加打印语句(类似于print ('in IF statement'),以便您知道哪个分支正在执行(或者,如果您熟悉SQL Proc调试,则可以对其进行调试)
  3. 删除try catch部分,查看是否由于某种原因而捕获了异常且未将其抛出。

哦,我刚刚看到,表中tipoVehiculo被定义为INT,但是您在proc中传递了NVARCHAR(15),这很可能就是您遇到问题的原因。