Загрузка данных


-- Обязательно ставим GO перед началом создания процедуры
GO

-- Если процедура уже существует, удаляем её
IF OBJECT_ID('sp_issue_book', 'P') IS NOT NULL
    DROP PROCEDURE sp_issue_book;
GO

-- Создаем процедуру с помощью стандартного CREATE PROCEDURE
CREATE PROCEDURE sp_issue_book
    @book_id INT,
    @reader_id INT
AS
BEGIN
    SET NOCOUNT ON;
    
    -- Проверка существования книги
    IF NOT EXISTS (SELECT 1 FROM Books WHERE book_id = @book_id)
    BEGIN
        RAISERROR('Ошибка: Книга с ID %d не найдена.', 16, 1, @book_id);
        RETURN;
    END

    -- Проверка существования читателя
    IF NOT EXISTS (SELECT 1 FROM Readers WHERE reader_id = @reader_id)
    BEGIN
        RAISERROR('Ошибка: Читатель с ID %d не найден.', 16, 1, @reader_id);
        RETURN;
    END

    -- Проверка наличия свободных экземпляров
    DECLARE @available_copies INT;
    SELECT @available_copies = copies_count FROM Books WHERE book_id = @book_id;

    IF @available_copies <= 0
    BEGIN
        RAISERROR('Ошибка: У книги (ID: %d) нет доступных экземпляров для выдачи.', 16, 1, @book_id);
        RETURN;
    END

    -- Выполнение транзакции выдачи книги
    BEGIN TRANSACTION;
    BEGIN TRY
        -- 1. Создание записи в таблице Loans
        INSERT INTO Loans (book_id, reader_id, loan_date, return_date)
        VALUES (@book_id, @reader_id, GETDATE(), NULL);

        -- 2. Уменьшение количества экземпляров в Books
        UPDATE Books
        SET copies_count = copies_count - 1
        WHERE book_id = @book_id;

        COMMIT TRANSACTION;
        PRINT 'Успех: Книга успешно выдана читателю.';
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
        RAISERROR(@ErrorMessage, 16, 1);
    END CATCH
END;
GO
GO

-- Удаляем триггер, если он уже существует
IF OBJECT_ID ('trg_check_loan_dates', 'TR') IS NOT NULL
    DROP TRIGGER trg_check_loan_dates;
GO

-- Создаем триггер с помощью стандартного CREATE TRIGGER
CREATE TRIGGER trg_check_loan_dates
ON Loans
AFTER INSERT, UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    -- Проверка: если дата возврата указана и она раньше даты выдачи
    IF EXISTS (
        SELECT 1 
        FROM inserted 
        WHERE return_date IS NOT NULL 
          AND return_date < loan_date
    )
    BEGIN
        RAISERROR('Ошибка валидации: Дата возврата книги не может быть раньше даты выдачи!', 16, 1);
        ROLLBACK TRANSACTION;
        RETURN;
    END
END;
GO