Показать сообщение отдельно
  #4  
Старый 29.10.2011, 01:41
chainik chainik вне форума
Начинающий
 
Регистрация: 30.06.2008
Сообщения: 140
Репутация: 8882
По умолчанию

/*---вот объявление функций пользователя.
Это оформляется в виде DLL. Я привожу этот пример только как рыбу.
Обрати внимание на способ передачи параметров- cdecl.
Это обязательное условие.
Этот текст надо оформить в виде DLL- библиотеки и поместить ее в
каталог C:\Interbase\Udf
*'/

Код:
library UdfMetrolog;

uses
  SysUtils, DateUtils;


function GetYear(var Dt:double):smallint;cdecl;
begin
    try
    GetYear:=YearOf(Dt);
    except
    GetYear:=9999
    end
end;

function GetMonth(var Dt:double):smallint;cdecl;
begin
    try
     Result:=MonthOf(Dt);
    except
    Result:=-1
    end
end;

function AddMonth(var Dt:double;var NumbOfMonth:integer):double;cdecl;
begin
    try
    Result:=IncMonth(Dt,NumbOfMonth);
    except
    Result:=-1
    end
end;

exports
AddMonth,
GetMonth,
GetYear;


begin
end.


После того как ты изготовил DLL с твоими функциями пользователя
на них можно ссылаться в тексте описания БД.
Для этого надо сделать внешние ссылки на эти функции, как это указано ниже.
Теперь твои функции можно применять также как и стандартные.
Надо сказать что такую возможность предоставляют не все базы данныз.
Лично я использую InterBase/FireBird, где все это есть.
*/

Код:
DECLARE EXTERNAL FUNCTION ADDMONTH DOUBLE PRECISION, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'AddMonth' MODULE_NAME 'UdfMetrolog';

DECLARE EXTERNAL FUNCTION GETMONTH DOUBLE PRECISION
RETURNS SMALLINT BY VALUE
ENTRY_POINT 'GetMonth' MODULE_NAME 'UdfMetrolog';

DECLARE EXTERNAL FUNCTION GETYEAR DOUBLE PRECISION
RETURNS SMALLINT BY VALUE
ENTRY_POINT 'GetYear' MODULE_NAME 'UdfMetrolog';
///// 2 /////////////////
Теперь о втором способе.
Можно в самой БД создать некое свойство, которое позволяет прямо по ходу дела
анализировать ситуацию и соответственно ее обрабатывать. Это триггеры- специальные процедуры,
внедренные в базу данных и запускающиеся автомтически при наступлении определенных событий в БД.
Например, процедура Workks_trig_ins (см ниже) автоматически запустится ПЕРЕД вставкой новой строки
в таблицу Works.
Код:
*--------------------------------------------------------------------------------------------------
  генератор номеров свидетельств в пределах 1 года для таблицы Works
    VidDocum IN ('  -  ','Сертифик. о калибр.','Свидет. о повер.','Извещ. о непригодн.','Акт на спис.')),
---------------------------------------------------------------------------------------------------*/
    CREATE TRIGGER Works_trig_ins FOR Works
ACTIVE BEFORE INSERT
AS
DECLARE VARIABLE Yr SMALLINT;
DECLARE VARIABLE Yr2 SMALLINT;
BEGIN
Yr2=extract(year from CURRENT_DATE);

/* свидетельство */
IF (NOT(NEW.Svidet IS NULL)) THEN
  BEGIN

  SELECT GETYEAR(Dat) FROM Works
        WHERE (Dat=(SELECT MAX(Dat) FROM Works
                           WHERE (VidDocum = NEW.VidDocum)))
  INTO :Yr;

  IF (NEW.VidDocum='Сертифик. о калибр.') then
    BEGIN
    NEW.NumSvidet_Yr = GEN_ID(Works_Kal_Yr_GEN,1);
    IF (:Yr <> :Yr2) THEN
           NEW.NumSvidet_Yr = GEN_ID(Works_Kal_Yr_GEN,1-NEW.NumSvidet_Yr);
    END

  IF (NEW.VidDocum='Свидет. о повер.') then
    BEGIN
    NEW.NumSvidet_Yr = GEN_ID(Works_Pov_Yr_GEN,1);
    IF (:Yr <> :Yr2) THEN
           NEW.NumSvidet_Yr = GEN_ID(Works_Pov_Yr_GEN,1-NEW.NumSvidet_Yr);
    END

  IF (NEW.VidDocum='Извещ. о непригодн.') then
    BEGIN
    NEW.NumSvidet_Yr = GEN_ID(Works_Negodn_Yr_GEN,1);
    IF (:Yr <> :Yr2) THEN
           NEW.NumSvidet_Yr = GEN_ID(Works_Negodn_Yr_GEN,1-NEW.NumSvidet_Yr);
    END

  IF (NEW.VidDocum='Акт на спис.') then
    BEGIN
    NEW.NumSvidet_Yr = GEN_ID(Works_Spisan_Yr_GEN,1);
    IF (:Yr <> :Yr2) THEN
           NEW.NumSvidet_Yr = GEN_ID(Works_Spisan_Yr_GEN,1-NEW.NumSvidet_Yr);
    END
  END
END!
/*
Итак, после всего этого база данных перестает быть просто хранилищем,
а приобретает определенный интеллект, чем программист должен уметь пользоваться.
После того как программист заложил в БД функции, она приобретает способность производить первичную обработку информации
и уже находится в состоянии, когда может по требованию пользователя выдать нужную информацию
(перед тем ее обработав и представив в нужном виде!).
Несколько советов
Эти 2 способа в какой- то мере конкурируют между собой. Какой из них избрать для достижения заданной цели-
решает программист.
Мой совет
В DLL следует помещать функции сложные. Они пишутся на языках высокого уровня и потому просты в отладке.
Оформмять твои специфические функции как триггеры следует тогда, когда они достаточно просты
и кроме того предвидится необходимость их изменять. Это так называемые Бизнес-правила.
Например, как триггер следует оформить функцию вычета подоходного налогга.
Если правила исчисления подоходного налога изменились- ты просто в твоей БД изменяешь эту функцию- и она
автоматически действует для всех пользователей.
*/
Ответить с цитированием