Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

курсач / Наволоцкий_1302_v2

.pdf
Скачиваний:
0
Добавлен:
27.12.2025
Размер:
2.69 Mб
Скачать

03_Procedures.sql

/*

============================================================

=====================

СКРИПТ 03: ХРАНИМЫЕ ПРОЦЕДУРЫ (BUSINESS LOGIC)

============================================================

===================== */

USE CircuitDB;

GO

PRINT '=========================================================== ==';

PRINT 'Создание хранимых процедур (Business Logic)...'; PRINT 'Время запуска: ' + CONVERT(VARCHAR(30), GETDATE(), 120);

PRINT '=========================================================== ==';

GO

/* =============================================

1. ПРОЦЕДУРА ПОИСКА (Search)

============================================= */

IF OBJECT_ID('[Stock].[usp_SearchComponents]', 'P') IS NOT

NULL DROP PROC [Stock].[usp_SearchComponents];

GO

81

CREATE PROCEDURE [Stock].[usp_SearchComponents]

@Keyword NVARCHAR(100) = NULL,

@ManufacturerID INT = NULL,

@CategoryID INT = NULL

AS

BEGIN

SET NOCOUNT ON;

SELECT c.ComponentID, c.PartNumber,

m.Name AS Manufacturer, cat.Name AS Category, p.Name AS Package, c.Description,

-- Генерируем дату "на лету" в момент вызова, в БД она не хранится

GETDATE() AS [ReportTime],

CASE WHEN c.IsActive = 1 THEN 'Yes' ELSE 'No' END AS [InProduction]

FROM [Stock].[Components] c

JOIN [Ref].[Manufacturers] m ON c.ManufacturerID = m.ManufacturerID

JOIN [Ref].[Categories] cat ON c.CategoryID = cat.CategoryID

JOIN [Ref].[PackageTypes] p ON c.PackageID = p.PackageID

WHERE

82

(@Keyword IS NULL OR c.PartNumber LIKE '%' + @Keyword + '%')

AND

(@ManufacturerID IS NULL OR c.ManufacturerID = @ManufacturerID)

AND

(@CategoryID IS NULL OR c.CategoryID = @CategoryID)

ORDER BY c.PartNumber;

END

GO

PRINT 'Proc [usp_SearchComponents] created.'; GO

/* =============================================

2. ПРОЦЕДУРА ДОБАВЛЕНИЯ (Create)

Исправлено: RAISERROR вместо THROW

============================================= */

IF OBJECT_ID('[Stock].[usp_CreateComponent]', 'P') IS NOT

NULL DROP PROC [Stock].[usp_CreateComponent];

GO

CREATE PROCEDURE [Stock].[usp_CreateComponent]

@PartNumber NVARCHAR(100),

@ManufacturerID INT,

@CategoryID INT,

@PackageID INT,

@Description NVARCHAR(1000) = NULL,

@NewID INT OUTPUT

AS

83

BEGIN

SET NOCOUNT ON;

-- Проверка до транзакции (так безопаснее для лога)

IF EXISTS (SELECT 1 FROM [Stock].[Components] WHERE

PartNumber = @PartNumber)

BEGIN

RAISERROR('Ошибка: Компонент с таким артикулом уже существует.', 16, 1);

RETURN;

END

BEGIN TRY

BEGIN TRANSACTION;

INSERT INTO [Stock].[Components] (PartNumber,

ManufacturerID, CategoryID, PackageID, Description,

IsActive)

VALUES (@PartNumber, @ManufacturerID, @CategoryID, @PackageID, @Description, 1);

SET @NewID = SCOPE_IDENTITY();

COMMIT TRANSACTION;

PRINT 'Компонент создан. ID: ' + CAST(@NewID AS VARCHAR(10)) + '. Время: ' + CONVERT(VARCHAR(30), GETDATE(), 120);

END TRY

84

BEGIN CATCH

-- Если случилась ошибка (например, сбой сети или

диска)

IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;

DECLARE @ErrMsg NVARCHAR(4000) = ERROR_MESSAGE();

RAISERROR(@ErrMsg, 16, 1);

END CATCH

END

GO

PRINT 'Proc [usp_CreateComponent] created.';

GO

/* =============================================

3. ПРОЦЕДУРА ОБНОВЛЕНИЯ (Update)

============================================= */

IF OBJECT_ID('[Stock].[usp_UpdateComponentStatus]', 'P') IS

NOT NULL DROP PROC [Stock].[usp_UpdateComponentStatus];

GO

CREATE PROCEDURE [Stock].[usp_UpdateComponentStatus]

@ComponentID INT,

@IsActive BIT,

@NewDescription NVARCHAR(1000) = NULL

AS

BEGIN

SET NOCOUNT ON;

85

IF NOT EXISTS (SELECT 1 FROM [Stock].[Components] WHERE

ComponentID = @ComponentID)

BEGIN

RAISERROR('Ошибка: Компонент с ID %d не найден.', 16, 1, @ComponentID);

RETURN;

END

UPDATE [Stock].[Components]

SET

IsActive = @IsActive,

Description = ISNULL(@NewDescription, Description)

WHERE ComponentID = @ComponentID;

PRINT 'Статус обновлен ' + CONVERT(VARCHAR(30), GETDATE(), 120);

END

GO

PRINT 'Proc [usp_UpdateComponentStatus] created.'; GO

/* =============================================

4. ПРОЦЕДУРА ЭКСПОРТА (XML Export)

Внимание: Мы используем английские имена колонок,

которые будут в View v_FullComponentReport (скрипт 04).

Дату создания убрали.

============================================= */

IF OBJECT_ID('[Stock].[usp_ExportReportToXML]', 'P') IS NOT

NULL DROP PROC [Stock].[usp_ExportReportToXML];

86

GO

CREATE PROCEDURE [Stock].[usp_ExportReportToXML]

AS

BEGIN

SET NOCOUNT ON;

--Вывод текущей даты генерации отчета как атрибута корневого элемента?

--Нет, просто генерируем данные.

--ВАЖНО: SSMS может подчеркивать v_FullComponentReport

красным,

-- так как View еще не создана. Это нормально, скрипт

выполнится.

 

SELECT

 

PartNumber

AS [@Article],

Manufacturer

AS [@Manufacturer],

Category

AS [@Category],

Package

AS [@Package],

Description

AS [@Description]

FROM [Stock].[v_FullComponentReport]

FOR XML PATH('Component'), ROOT('CircuitReport');

END

GO

PRINT 'Proc [usp_ExportReportToXML] created.'; GO

/* =============================================

87

5. ПРОЦЕДУРА ИМПОРТА (XML Import)

Исправлено: RAISERROR и обработка ошибок

============================================= */

IF OBJECT_ID('[Stock].[usp_ImportComponentsFromXML]', 'P')

IS NOT NULL DROP PROC [Stock].[usp_ImportComponentsFromXML];

GO

CREATE PROCEDURE [Stock].[usp_ImportComponentsFromXML]

@XmlData XML

AS

BEGIN

SET NOCOUNT ON;

IF @XmlData IS NULL

BEGIN

RAISERROR('Ошибка: Передан пустой XML.', 16, 1); RETURN;

END

BEGIN TRY

BEGIN TRANSACTION;

INSERT INTO [Stock].[Components] (PartNumber,

ManufacturerID, CategoryID, PackageID, Description,

IsActive)

SELECT

Node.value('@Article', 'NVARCHAR(100)'),

-- Ищем ID по имени. Если не нашли - ставим 1 (по умолчанию)

88

ISNULL((SELECT Top 1 ManufacturerID FROM

[Ref].[Manufacturers] WHERE Name =

Node.value('@Manufacturer', 'NVARCHAR(100)')), 1),

ISNULL((SELECT Top 1 CategoryID FROM [Ref].[Categories] WHERE Name = Node.value('@Category', 'NVARCHAR(100)')), 1),

ISNULL((SELECT Top 1 PackageID FROM [Ref].[PackageTypes] WHERE Name = Node.value('@Package', 'NVARCHAR(100)')), 1),

Node.value('@Description', 'NVARCHAR(1000)'), 1

FROM @XmlData.nodes('/CircuitReport/Component') AS

T(Node)

WHERE NOT EXISTS (

-- Защита от дубликатов по Артикулу

SELECT 1 FROM [Stock].[Components] c

WHERE c.PartNumber = Node.value('@Article', 'NVARCHAR(100)')

);

DECLARE @Count INT = @@ROWCOUNT;

COMMIT TRANSACTION;

PRINT 'Импортировано компонентов: ' + CAST(@Count AS VARCHAR(10));

END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;

89

DECLARE @Err NVARCHAR(4000) = ERROR_MESSAGE();

RAISERROR(@Err, 16, 1);

END CATCH

END

GO

PRINT 'Proc [usp_ImportComponentsFromXML] created.'; GO

PRINT '=========================================================== ==';

PRINT 'Скрипт 03 выполнен успешно.';

PRINT 'Время завершения: ' + CONVERT(VARCHAR(30), GETDATE(), 120);

PRINT '=========================================================== ==';

GO

90

Соседние файлы в папке курсач