
- •Методические указания к дипломному проектированию
- •Введение
- •Организация дипломного проектирования
- •Тематика дипломных проектов
- •Общие требования к дипломному проекту
- •Структура пояснительной записки
- •3.1.1 Титульный лист
- •3.1.2 Техническое задание
- •3.1.3 Реферат
- •3.1.4 Содержание
- •3.1.5 Введение
- •3.1.6 Раздел разработки программного обеспечения
- •3.1.7 Заключение
- •3.1.8 Список использованных источников
- •3.1.9 Приложения
- •Графическая часть
- •Рекомендации к структуре и оформлению раздела разработки программного обеспечения
- •Анализ предметной области
- •Модель предметной области в языке uml
- •Диаграммы методологии idef1
- •Модель «сущность – связь» в нотации idef1x
- •Анализ требований
- •Модель вариантов использования
- •Функциональное моделирование в нотации idef0
- •Модель анализа вариантов использования
- •Проектирование
- •Модель проектирования
- •Модель развертывания
- •Реализация
- •Модель реализации
- •Модель тестирования
- •Примеры описания процесса разработки
- •Разработка программных средств банковской системы
- •Пример проктирования базы данных
- •Into :TheInitialValue;
- •If( TheInitialValue is null ) then exit;
- •Into :TheSum;
- •Insert into AccountInheritance(AccountFolderId, SubAccountId) values(:NewId, :NewId);
- •Insert into AccountInheritance(AccountFolderId, SubAccountId) values(:ParentId, :NewId);
- •Into :TheInitialValue;
- •If( TheInitialValue is null ) then exit;
- •Into :TheSum;
- •Подготовка и защита дипломного проекта
- •Подготовка к защите
- •Защита дипломного проекта
- •Требования к презентации и раздаточному материалу
- •Примеры оформления пояснительной записки
- •Титульный лист
- •Задание
- •Реферат
- •Содержание
- •Ведомость дипломного проекта
- •Листинг программы
- •If (UndoPolicy.CanUndo())
- •Краткое справочное руководство
- •Б1 Методология структурного анализа и проектирования idef0
- •Б2 Методология информационного менеджмента idef1
- •Б3 Методология инфологического проектирования idef1x
- •Б4 Универсальный язык моделирования uml
- •Б5 еспд. Общие требования к текстовым документам
- •Б6 Примеры схем гост 19.701-90
- •Литература
Into :TheInitialValue;
If( TheInitialValue is null ) then exit;
SELECT
SUM(AMovement.Quantity * AMovement.UnitCost)
FROM
AMovement
INNER JOIN AnEconomicOperation EOp ON (AMovement.EconomicOperationId = EOp.Id)
WHERE
(AMovement.DebitAccountId IN (SELECT SubAccountId FROM AccountInheritance WHERE (AccountFolderId = :AccountId)))
AND
(EOp.BeginsWith < :ReqDate)
Into :TheSum;
IF ( TheSum IS NULL ) THEN TheSum = 0;
DebitBalance = TheInitialValue + TheSum;
END
Бывает, что соединения таблиц выполняются SQL-серверами более эффективно, чем вложенные запросы. Соответственно, вложенный запрос в этой хранимой процедуре можно переписать как соединение таблиц, однако, во-первых, оптимизаторы многих SQL-серверов в таком случае автоматически производят реинтерпретацию, во-вторых, подобные ручные оптимизации стоит проводить, только если производительность сервера оказывается недостаточной на рабочих объёмах данных.
Для поддержки актуальности таблицы "Наследование счёта" необходимо описать соответсвующие триггеры:
SET TERM !! ;
CREATE PROCEDURE GetAccountParents(ASubAccountId INTEGER) RETURNS(AnAccountFolderId INTEGER)
AS
BEGIN
/* Selects thread of parents of account from bottom to top */
WHILE( EXISTS(SELECT * FROM ASubAccount WHERE (Id = :ASubAccountId)) ) DO
BEGIN
SELECT AccountFolderId FROM ASubAccount WHERE (Id = :ASubAccountId) INTO :AnAccountFolderId;
SUSPEND;
ASubAccountId = AnAccountFolderId;
END
END !!
SET TERM ; !!
SET TERM !! ;
CREATE TRIGGER TI_AnAccount_Inherit FOR AnAccount
AFTER INSERT
AS
DECLARE VARIABLE NewId INTEGER;
DECLARE VARIABLE ParentId INTEGER;
BEGIN
NewId = NEW.Id;
Insert into AccountInheritance(AccountFolderId, SubAccountId) values(:NewId, :NewId);
FOR
SELECT AnAccountFolderId FROM GetAccountParents(:NewId) INTO :ParentId
DO
BEGIN
Insert into AccountInheritance(AccountFolderId, SubAccountId) values(:ParentId, :NewId);
END
END !!
SET TERM ; !!
SET TERM !! ;
CREATE TRIGGER TD_AnAccount_Inherit FOR AnAccount
AFTER DELETE
AS
DECLARE VARIABLE OldId INTEGER;
BEGIN
OldId = OLD.Id;
DELETE FROM AccountInheritance WHERE (SubAccountId = :OldId);
END !!
SET TERM ; !!
COMMIT;
Кроме того, определим несколько представлений для удобства восприятия БД:
CREATE VIEW AnAccountTreeView (Id, AccountFolderId, Code, DisplayLabel) AS
SELECT ACustomAccount.Id, ASubAccount.AccountFolderId, ACustomAccount.Code, ACustomAccount.DisplayLabel
FROM ACustomAccount LEFT OUTER JOIN ASubAccount ON ( ACustomAccount.Id = ASubAccount.Id)
Многие разработчики из соображений оптимизации информационной системы по скорости также хранят такие промежуточные данные, как обороты по счетам и корреспондирующим счетам за определённый промежуток времени. По моему мнению, подтверждённому личной практикой, такая оптимизация не оправдывает себя как по выигрышу в скорости, так и по затратам на реализацию.
Специализация шаблонов физических объектов
CASE-инструментарий предоставляет возможность описывать шаблоны таких объектов БД, как хранимые процедуры и триггеры. Кроме того, можно описывать шаблоны скриптов.
Для независимых сущностей мы определяем генераторы для суррогатных ключей и хранимые процедуры для создания записей.
Шаблон CreateGenerator (PreScript For Table)
CREATE GENERATOR %TableNameGenerator%DBMSDelim
SET GENERATOR %TableNameGenerator TO 0%DBMSDelim
Шаблон CreateRec (Stored Procedure For Table)
CREATE PROCEDURE Create%TableNameRec(%ForEachAtt() {
%If( %Not( %AttIsPK) ) {
%AttFieldName %AttPhysDatatype, } }
Dummy INTEGER) RETURNS(Id INTEGER)
AS
BEGIN
Id = GEN_ID(%TableNameGenerator, 1)%DBMSDelim
INSERT INTO %TableName(%ForEachAtt() {
%If( %Not( %AttIsPK) ) {
%AttFieldName, } } Id) VALUES ( %ForEachAtt() {
%If( %Not( %AttIsPK) ) {
:%AttFieldName, } } :Id )%DBMSDelim
END
Создание деловых правил
В числе прочих мы можем создать, например, такие правила:
SET TERM !! ;
CREATE PROCEDURE CreateAnAccountRec(Code VARCHAR(20), DisplayLabel VARCHAR(80),
IsActive INTEGER, IsPassive INTEGER,
InBalance INTEGER, ParentCode VARCHAR(20), Dummy INTEGER) RETURNS(Id INTEGER)
AS
DECLARE VARIABLE ParentAccountId INTEGER;
DECLARE VARIABLE ParentInBalance INTEGER;
DECLARE VARIABLE ParentIsActive INTEGER;
DECLARE VARIABLE ParentIsPassive INTEGER;
BEGIN
IF( (IsActive = 0) AND (IsPassive = 0) ) THEN
BEGIN
IsActive = 1;
IsPassive = 1;
END
SELECT Id, InBalance, IsActive, IsPassive
FROM ACustomAccount
WHERE Code = :ParentCode
INTO :ParentAccountId, :ParentInBalance, :ParentIsActive, :ParentIsPassive;
IF( ParentAccountId IS NULL ) THEN
BEGIN
ParentInBalance = InBalance;
ParentIsActive = IsActive;
ParentIsPassive = IsPassive;
END
EXECUTE PROCEDURE CreateACustomAccountRec(Code, DisplayLabel, ParentIsActive, ParentIsPassive,
ParentInBalance, Dummy) RETURNING_VALUES(Id);
/* check for parent account */
IF( (Id > 0) AND (ParentAccountId IS NOT NULL) ) THEN
BEGIN
/* check parent account for folder */
IF( NOT EXISTS( SELECT * FROM AnAccountFolder WHERE Id = :ParentAccountId ) ) THEN
BEGIN
INSERT
INTO AnAccountFolder(Id)
VALUES(:ParentAccountId);
END
INSERT
INTO ASubAccount(Id, AccountFolderId)
VALUES(:Id, :ParentAccountId);
END
END !!
SET TERM ; !!
SET TERM !! ;
CREATE PROCEDURE DoMovement(DebitAccountId INTEGER, CreditAccountId INTEGER, EcOpId INTEGER,
Quantity INTEGER, UnitCost DOUBLE PRECISION) RETURNS(Id INTEGER)
AS
BEGIN
IF( NOT EXISTS( SELECT * FROM AnAccount WHERE Id = :DebitAccountId ) ) THEN
BEGIN
INSERT INTO AnAccount(Id, InitialDebitValue, InitialCreditValue) VALUES(:DebitAccountId, 0.0, 0.0);
END
IF( NOT EXISTS( SELECT * FROM AnAccount WHERE Id = :CreditAccountId ) ) THEN
BEGIN
INSERT INTO AnAccount(Id, InitialDebitValue, InitialCreditValue) VALUES(:CreditAccountId, 0.0, 0.0);
END
EXECUTE PROCEDURE CreateAMovementRec(EcOpId, CreditAccountId, DebitAccountId, 'NOW',
Quantity, UnitCost, 0) RETURNING_VALUES(ID);
END !!
SET TERM ; !!
SET TERM !! ;
CREATE PROCEDURE DoMovementByCode(DebitAccountCode VARCHAR(20), CreditAccountCode VARCHAR(20),
EcOpId INTEGER, Quantity INTEGER,
UnitCost DOUBLE PRECISION) RETURNS(Id INTEGER)
AS
DECLARE VARIABLE DebitAccountId INTEGER;
DECLARE VARIABLE CreditAccountId INTEGER;
BEGIN
SELECT Id FROM ACustomAccount WHERE Code = :DebitAccountCode INTO :DebitAccountId;
SELECT Id FROM ACustomAccount WHERE Code = :CreditAccountCode INTO :CreditAccountId;
EXECUTE PROCEDURE DoMovement(DebitAccountId, CreditAccountId, EcOpId, Quantity, UnitCost)
RETURNING_VALUES(ID);
END !!
SET TERM ; !!
SET TERM !! ;
CREATE PROCEDURE GetDebitBalanceAllOn(ReqDate DATE) RETURNS(DebitBalance DOUBLE PRECISION)
AS
DECLARE VARIABLE TheInitialValue DOUBLE PRECISION;
DECLARE VARIABLE TheSum DOUBLE PRECISION;
BEGIN
SELECT
SUM(A.InitialDebitValue)
FROM
AnAccount A
INNER JOIN ACustomAccount CA ON (A.Id = CA.Id)
WHERE
(CA.InBalance = 1)