Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / построение иерархических справочников / 14 сообщений из 14, страница 1 из 1
15.06.2004, 15:09
    #32561809
Druzzzzz
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
проблема построения иерархической структуры(дерева) справочников товаров
есть товары, группы, подгруппы и в принципе уровень вложености не ограничен
товар может лежать на любом уровне вложенности, т.е. входить в группу, и не входить ни в одну из нижележащих. как грамотно построить базу, чтобы все товары лежали в одной таблице, и при этом сохранялась иерархия.
если строить обычным образом группа-подгруппа-...-товар ограничевается вложенность, и товар попадает в таблицы с группами, подгруппами и т.д., т.е. номенклатура конечного товара бъётся на несколько таблиц.
другое решение создается таблица вида
Код: plaintext
1.
2.
3.
4.
5.
6.
ID_primary ID_group Name_group
xxxxxxxx     1000000  группа1
xxxxxxxx     1100000  подгруппа11
xxxxxxxx     1110000  подгруппа111
xxxxxxxx     2000000  группа2
xxxxxxxx     2100000  подгруппа21 и т.д.
а таблица товаров соответственно связана по ID_primary
но тогда возникает вопрос об автообработке ID_group и построении
иерархии.
есть и третье решение
две таблицы
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
id_head(primary) name	      id_tail
1                    группа1          5
2                    подгруппа11      6
3                    подгруппа12      7
4                    группа2          8
и вторая 
id_tail(primary) id_head
5                  1
6                  1
7                  1
8                  4
соответственно в запросах через связи получаем то что надо. это решение
пока до конца не обдумано.
если есть у кого идеи, или кто уже нечто подобное реализовывал,
поделитесь плз.
...
Рейтинг: 0 / 0
15.06.2004, 15:22
    #32561845
Вася
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
http://www.osp.ru/os/2004/02/062_print.htm
для тебя смотри про деревья
...
Рейтинг: 0 / 0
16.06.2004, 06:24
    #32562719
Klick
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
Это будет справочник групп:
ID
Parent
Name

и спр товаров:
ID
Group_ID
Name ну и т.д.

Тут и думать нефига. Читай про деревья. так и только так правильно организовывать их!
...
Рейтинг: 0 / 0
16.06.2004, 11:29
    #32563146
Серега
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
KlickЭто будет справочник групп:
ID
Parent
Name

и спр товаров:
ID
Group_ID
Name ну и т.д.

Тут и думать нефига. Читай про деревья. так и только так правильно организовывать их!
Думать надо всегда. 8-)
Я бы сделал по другому. 2 таблицы.

1.Товары
T_Id -ключ
Name -наименование
Any -всяко разно (опционально)

2.Дерево
Id -ключ
Parent_id -родительский ключ
T_id -ссылка на товары
Kol -количество (опционально)
Any -всяко разно (опционально)

Такая структура позволяет строить "неправильные" деревья, когда один и тот же товар может входить в несколько групп/изделий. Таблу товаров, в принципе, тоже можно сделать деревянной, для описания сложных, но поддерживать все это вместе намного сложнее.
...
Рейтинг: 0 / 0
16.06.2004, 17:53
    #32564286
mv
mv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
У меня такая штука реализована. Все в одной табличке (part).

База - FireBird 1.5.

Реализованы - уровни/подуровни ("каталоги"), пакеты ("составной товар"), ссылки (определяешь один базовый товар, а в "ссылках" меняешь, некоторые мелочи (ну, там, цену, например, или номер версии)). Отображаю с помощью компонента TVirtualTreeView (использую Delphi 7).

Для ссылки на родительскую запись используется значение поля Base_part_id, для ссылки из "ссылки" на породившую запись - использую POINTER_PART_ID. Кроме того, (некоторая денормализация, конечно) - для определения, что это за запись - ссылка или реальный узел дерева - использую поле BOOLEAN_PART_OR_REFERENCE. LOCATION - для задания позиции записи при отображения записи в текущем уровне дерева.
CHILD_COUNT - счетчик дочерних записей, используется для ускорения формирования запросов. Тип конкретного узла определяется значением NODE_CATEGORY. Запросы к дереву формируются с помощью хранимой процедуры GET_TREE_PART(MASTER_PART_ID : integer) - параметр - Id узла, с которого надо начинать выборку.

Почти вся функциональность реализована с помщью треггеров и хранимых процедур.

Вот кое - какой код (лишнюю шнягу повыкидывал) :

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
 /******************************************************************************/ 
 /***               Generated by IBExpert 16.06.2004 17:18:05                ***/ 
 /******************************************************************************/ 

SET SQL DIALECT  3 ;

SET NAMES WIN1251;



 /******************************************************************************/ 
 /***                                 Tables                                 ***/ 
 /******************************************************************************/ 
CREATE GENERATOR PART_ID_GEN;

CREATE TABLE PART (
    PART_ID                    T_PART_ID NOT NULL  /* T_PART_ID = INTEGER */ ,
    TYPE_BILL_ID               T_TYPE_BILL_ID  /* T_TYPE_BILL_ID = INTEGER */ ,
    MAIN_PART_ID               T_MAIN_PART_ID  /* T_MAIN_PART_ID = INTEGER */ ,
    UNIT_ID                    T_UNIT_ID  /* T_UNIT_ID = INTEGER */ ,
    DEPARTMENT_ID              T_DEPARTMENT_ID  /* T_DEPARTMENT_ID = INTEGER */ ,
    PART_CATEGORY_ID           T_PART_CATEGORY_ID  /* T_PART_CATEGORY_ID = INTEGER */ ,
    BASE_PART_ID               T_BASE_PART_ID NOT NULL  /* T_BASE_PART_ID = INTEGER */ ,
    POINTER_PART_ID            T_POINTER_PART_ID  /* T_POINTER_PART_ID = INTEGER */ ,
    REG_DATE                   T_REG_DATE  /* T_REG_DATE = DATE DEFAULT 'NOW' */ ,
    REG_TIME                   T_REG_TIME  /* T_REG_TIME = TIME DEFAULT 'NOW' */ ,
    FNAME_SHORT                T_FNAME_SHORT  /* T_FNAME_SHORT = VARCHAR(84) */ ,
    FNAME                      T_FNAME  /* T_FNAME = VARCHAR(150) */ ,
    COMMENT                    T_COMMENT  /* T_COMMENT = VARCHAR(250) */ ,
    BOOLEAN_GOODS_OR_SERVICE   T_BOOLEAN_GOODS_OR_SERVICE  /* T_BOOLEAN_GOODS_OR_SERVICE = INTEGER DEFAULT 0 NOT NULL CHECK (VALUE IN (0, 1)) */ ,
    VERSION_CODE               T_VERSION_CODE  /* T_VERSION_CODE = VARCHAR(250) */ ,
    VERSION_BUILD              T_VERSION_BUILD  /* T_VERSION_BUILD = VARCHAR(250) */ ,
    SUMMA_PRICE                T_SUMMA_PRICE  /* T_SUMMA_PRICE = NUMERIC(12,2) DEFAULT 0 NOT NULL */ ,
    QUANTITY                   T_QUANTITY  /* T_QUANTITY = NUMERIC(14,4) DEFAULT 1 NOT NULL */ ,
    QUANTITY_TOTAL             T_QUANTITY_TOTAL  /* T_QUANTITY_TOTAL = NUMERIC(14,4) DEFAULT 1 NOT NULL */ ,
    SUMMA_NO_TAX_RATE          T_SUMMA_NO_TAX_RATE  /* T_SUMMA_NO_TAX_RATE = NUMERIC(12,2) DEFAULT 0 NOT NULL */ ,
    PC_TAX_RATE                T_PC_TAX_RATE DEFAULT  0   /* T_PC_TAX_RATE = NUMERIC(12,4) DEFAULT 0 NOT NULL */ ,
    SUMMA_TAX_RATE             T_SUMMA_TAX_RATE  /* T_SUMMA_TAX_RATE = NUMERIC(12,2) DEFAULT 0 NOT NULL */ ,
    SUMMA                      T_SUMMA  /* T_SUMMA = NUMERIC(12,2) DEFAULT 0 NOT NULL */ ,
    NODE_CATEGORY              T_NODE_CATEGORY  /* T_NODE_CATEGORY = VARCHAR(6) NOT NULL CHECK (VALUE IN ('Ветка', 'Лист', 'Пакет', 'Фантом')) */ ,
    BOOLEAN_PART_OR_REFERENCE  T_BOOLEAN_PART_OR_REFERENCE  /* T_BOOLEAN_PART_OR_REFERENCE = INTEGER DEFAULT 0 NOT NULL CHECK (VALUE IN (0, 1)) */ ,
    LOCATION                   T_LOCATION  /* T_LOCATION = INTEGER DEFAULT 0 */ ,
    CHILD_COUNT                T_CHILD_COUNT  /* T_CHILD_COUNT = INTEGER DEFAULT 0 NOT NULL */ 
);





 /******************************************************************************/ 
 /***                              Primary Keys                              ***/ 
 /******************************************************************************/ 

ALTER TABLE PART ADD PRIMARY KEY (PART_ID);


 /******************************************************************************/ 
 /***                                Indices                                 ***/ 
 /******************************************************************************/ 

CREATE INDEX XIE1PART ON PART (POINTER_PART_ID);
CREATE INDEX XIE2PART ON PART (LOCATION);
CREATE INDEX XIE3PART ON PART (NODE_CATEGORY);
CREATE INDEX XIE4PART ON PART (BASE_PART_ID);
CREATE INDEX XIF146PART ON PART (PART_CATEGORY_ID);
CREATE INDEX XIF156PART ON PART (DEPARTMENT_ID);
CREATE INDEX XIF168PART ON PART (UNIT_ID);
CREATE INDEX XIF185PART ON PART (MAIN_PART_ID);
CREATE INDEX XIF186PART ON PART (TYPE_BILL_ID);


 /******************************************************************************/ 
 /***                                Triggers                                ***/ 
 /******************************************************************************/ 


SET TERM ^ ;




 /* Trigger: PART_AD */ 
CREATE TRIGGER PART_AD FOR PART
ACTIVE AFTER DELETE POSITION  0 
AS
DECLARE VARIABLE numrows INTEGER;
BEGIN

.....

 /* Part ссылается на формирующую деталь Part Запрет удаления родительской записи */ 
    select count(*)
      from Part
      where
        Part.part_id = OLD.part_id into numrows;
    IF (numrows >  0 ) THEN
    BEGIN
      EXCEPTION CUSTOM_RESTRICT 'Удалять нельзя: имеются записи в связанной таблице "Прайс"';
    END

...
END
^

 /* Trigger: PART_AU */ 
CREATE TRIGGER PART_AU FOR PART
ACTIVE AFTER UPDATE POSITION  0 
AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
...
 /* Part ссылается на формирующую деталь Part Запрет изменения родительской записи */ 
  IF
    (OLD.part_id <> NEW.part_id) THEN
  BEGIN
    select count(*)
      from Part
      where
        Part.part_id = OLD.part_id into numrows;
    IF (numrows >  0 ) THEN
    BEGIN
      EXCEPTION CUSTOM_RESTRICT 'Изменять нельзя: имеются записи в связанной таблице "Прайс"';
    END
  END

...

END
^

 /* Trigger: PART_GEN_ID */ 
CREATE TRIGGER PART_GEN_ID FOR PART
ACTIVE BEFORE INSERT POSITION  0 
as
begin 
    IF (new.Part_id IS NULL) THEN
       new.Part_id = GEN_ID(Part_id_gen,  1 );
end
^

 /* Trigger: PART_POINTER_AD */ 
CREATE TRIGGER PART_POINTER_AD FOR PART
ACTIVE AFTER DELETE POSITION  0 
AS
 /* При удалении детали
  удалять и соответсвующие детали пакетов */ 
BEGIN
  if (old.boolean_part_or_reference =  0 ) then
  begin
    delete from Part
    where Part.pointer_Part_id =
          old.Part_id;
  end
END
^

 /* Trigger: PART_POINTER_BU */ 
CREATE TRIGGER PART_POINTER_BU FOR PART
ACTIVE BEFORE UPDATE POSITION  0 
AS
 /* При изменении детали изменять и 
   соотв. детали пакетов*/ 
BEGIN
 /* При изменении детали изменять и 
   соотв. детали пакетов*/ 
 /* Если это не перемещение...*/ 
if ((new.Part_id = old.Part_id)
   and ((old.node_category = 'Лист')
      or(old.node_category = 'Пакет'))
   and (old.boolean_part_or_reference =  0 ))  then begin

 /* Если есть ссылки на элемент*/ 
  if (exists (select Part_id from Part
               where Part.pointer_Part_id = old.Part_id)) then
  begin

   /* Переносим Код вида счета */ 
    if ((old.type_bill_id <> new.type_bill_id)
     or (old.type_bill_id is not null) and
        (new.type_bill_id is null)
     or (old.type_bill_id is null) and
        (new.type_bill_id is not null)) then begin
      update Part set type_bill_id = new.type_bill_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код главной номенклатуры */ 
    if ((old.main_part_id <> new.main_part_id)
     or (old.main_part_id is not null) and
        (new.main_part_id is null)
     or (old.main_part_id is null) and
        (new.main_part_id is not null)) then begin
      update Part set main_part_id = new.main_part_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код ед измер */ 
    if ((old.unit_id <> new.unit_id)
     or (old.unit_id is not null) and
        (new.unit_id is null)
     or (old.unit_id is null) and
        (new.unit_id is not null)) then begin
      update Part set unit_id = new.unit_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код подразделения */ 
    if ((old.department_id <> new.department_id)
     or (old.department_id is not null) and
        (new.department_id is null)
     or (old.department_id is null) and
        (new.department_id is not null)) then begin
      update Part set department_id = new.department_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код категории товара */ 
    if ((old.part_category_id <> new.part_category_id)
     or (old.part_category_id is not null) and
        (new.part_category_id is null)
     or (old.part_category_id is null) and
        (new.part_category_id is not null)) then begin
      update Part set part_category_id = new.part_category_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Полн. наименование */ 
    if ((old.fname_short <> new.fname_short)
     or (old.fname_short is not null) and
        (new.fname_short is null)
     or (old.fname_short is null) and
        (new.fname_short is not null)) then begin
      update Part set fname_short = new.fname_short
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Полное наименование */ 
    if ((old.fname <> new.fname)
     or (old.fname is not null) and
        (new.fname is null)
     or (old.fname is null) and
        (new.fname is not null)) then begin
      update Part set fname = new.fname
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Товар/Услуга */ 
    if ((old.boolean_goods_or_service <> new.boolean_goods_or_service)
     or (old.boolean_goods_or_service is not null) and
        (new.boolean_goods_or_service is null)
     or (old.boolean_goods_or_service is null) and
        (new.boolean_goods_or_service is not null)) then begin
      update Part set boolean_goods_or_service = new.boolean_goods_or_service
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код версии */ 
    if ((old.version_code <> new.version_code)
     or (old.version_code is not null) and
        (new.version_code is null)
     or (old.version_code is null) and
        (new.version_code is not null)) then begin
      update Part set version_code = new.version_code
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Сборка */ 
    if ((old.version_build <> new.version_build)
     or (old.version_build is not null) and
        (new.version_build is null)
     or (old.version_build is null) and
        (new.version_build is not null)) then begin
      update Part set version_build = new.version_build
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Цена */ 
    if ((old.summa_price <> new.summa_price)
     or (old.summa_price is not null) and
        (new.summa_price is null)
     or (old.summa_price is null) and
        (new.summa_price is not null)) then begin
      update Part set summa_price = new.summa_price
      where old.Part_id = Part.pointer_Part_id;
      execute procedure recount_references_Part(old.Part_id); 

    end

 /* Переносим Ставка налога, % */ 
    if ((old.pc_tax_rate <> new.pc_tax_rate)
     or (old.pc_tax_rate is not null) and
        (new.pc_tax_rate is null)
     or (old.pc_tax_rate is null) and
        (new.pc_tax_rate is not null)) then begin
      update Part set pc_tax_rate = new.pc_tax_rate
      where old.Part_id = Part.pointer_Part_id;
      execute procedure recount_references_Part(old.Part_id); 

    end



  end
end
END
^

 /* Trigger: PART_QUANTITY_ADD */ 
CREATE TRIGGER PART_QUANTITY_ADD FOR PART
ACTIVE BEFORE INSERT POSITION  2 
as
declare variable P_Node_Category VARCHAR( 6 );
declare variable P_Quantity_Total NUMERIC ( 14 , 4 );
declare variable Koeff NUMERIC ( 14 , 4 );
 /*Генерируется, только если есть такое поле:*/ 
declare variable P_Boolean_Part_Or_Reference INTEGER;


BEGIN
   /* Добавление: если добавляем не ссылку, а лист или пакет, то
     посмотреть количество у родителя, и,
     если он пакет, и умножить количество родителя на текущее количество */ 
  Koeff =  1 ;
  if ((new.Node_Category IN  ('Лист', 'Пакет')) 
  and (new.BASE_Part_ID >  0 )
 /*Генерируется, только если есть такое поле:*/ 
  and (new.Boolean_Part_Or_Reference =  0 )
) then begin
    select Node_Category, 
 /*Генерируется, только если есть такое поле:*/ 
  Boolean_Part_Or_Reference,
Quantity_Total from Part T
      where T.Part_ID = new.BASE_Part_ID into
      P_Node_Category,
 /*Генерируется, только если есть такое поле:*/ 
  P_Boolean_Part_Or_Reference,
      P_Quantity_Total;
    if ((P_Node_category = 'Пакет') 
 /*Генерируется, только если есть такое поле:*/ 
  and (P_Boolean_Part_Or_Reference =  0 )

) then
        Koeff = P_Quantity_Total; 
  end
  new.Quantity_Total = new.Quantity * Koeff; 

END
^

 /* Trigger: PART_QUANTITY_UPD */ 
CREATE TRIGGER PART_QUANTITY_UPD FOR PART
ACTIVE BEFORE UPDATE POSITION  2 
as
declare variable P_Node_Category VARCHAR( 6 );
declare variable P_Quantity_Total NUMERIC ( 14 , 4 );
declare variable Koeff NUMERIC ( 14 , 4 );
declare variable P_Boolean_Part_Or_Reference INTEGER;

BEGIN    
   /* Узел-не-ссылка-и-(лист или пакет) переместился или изменилось количество: то
   посмотреть общее количество у родителя, и,
   если родитель пакет, получить новое общее количество, умножив общее количество родителя на текущее количество */ 
  Koeff =  1 ;
  if ((new.Node_Category IN  ('Лист', 'Пакет')) 
    and (new.Boolean_Part_Or_Reference =  0 )


) then begin

    if ((old.Base_Part_ID <> new.Base_Part_ID) 
      or(old.Quantity <> new.Quantity) ) then begin  /* Перемещение */ 
      if (new.BASE_Part_ID >  0 ) then begin
        select Node_Category, 
        Boolean_Part_Or_Reference,

        Quantity_Total from Part T
          where (T.Part_ID = new.BASE_Part_ID) into
          P_Node_Category, 
          P_Boolean_Part_Or_Reference,

          P_Quantity_Total;
        if ((P_Node_category = 'Пакет') 
        and (P_Boolean_Part_Or_Reference =  0 )


      ) then
          Koeff = P_Quantity_Total; 
      end   
      new.Quantity_Total = new.Quantity * Koeff; 
    end

    if ((new.Quantity_Total <> old.Quantity_Total) 
    and (new.Node_Category = 'Пакет')) then
      update Part T set 
        T.Quantity_Total = T.Quantity * new.Quantity_Total
        where ((T.Base_Part_Id = New.Part_Id) 
         and  (T.Node_Category IN  ('Лист', 'Пакет')) 
        and (T.Boolean_Part_Or_Reference =  0 )

); 
  end
END
^

 /* Trigger: PART_SUMM_ADD */ 
CREATE TRIGGER PART_SUMM_ADD FOR PART
ACTIVE BEFORE INSERT POSITION  2 
as
BEGIN    
  if ((new.base_Part_id >  0 ) and (new.summa <>  0 )) then begin
     /* Если от чего-то наследуется, родителю передать сумму*/ 
    update Part T set
      T.summa_price = T.summa_price + new.summa
      where T.Part_id = new.base_Part_id;
    execute procedure recount_Part(new.base_Part_id);
  end
END
^

 /* Trigger: PART_SUMM_DEL */ 
CREATE TRIGGER PART_SUMM_DEL FOR PART
ACTIVE BEFORE DELETE POSITION  2 
as
BEGIN    
  if ((old.base_Part_id >  0 ) and (old.summa <>  0 )) then begin
   /* Если от чего-то наследовался, у родителя вычесть сумму*/ 
    update Part T set
      T.summa_price = T.summa_price - old.summa
      where T.Part_id = old.base_Part_id;
    execute procedure recount_Part(old.base_Part_id);
  end
END
^

 /* Trigger: PART_SUMM_UPD */ 
CREATE TRIGGER PART_SUMM_UPD FOR PART
ACTIVE BEFORE UPDATE POSITION  2 
as
BEGIN    
  if ((old.base_Part_id >  0 ) and (old.summa <>  0 )) then begin
   /* Если от чего-то наследовался, у бывшего родителя вычесть сумму*/ 
    update Part T set
      T.summa_price = T.summa_price - old.summa
      where T.Part_id = old.base_Part_id;
    execute procedure recount_Part(old.base_Part_id);
  end
  if ((new.base_Part_id >  0 ) and (new.summa <>  0 )) then begin
   /* Если будет от чего-то наследоваться, новому родителю передать сумму*/ 
    update Part T set
      T.summa_price = T.summa_price + new.summa
      where T.Part_id = new.base_Part_id;
    execute procedure recount_Part(new.base_Part_id);
  end
END
^

 /* Trigger: PART_TREE_BIUD */ 
CREATE TRIGGER PART_TREE_BIUD FOR PART
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION  99 
as
BEGIN    --  Прайс - обеспечение фукционирования как дерева
 
  if (inserting or updating) then begin
    if (new.base_Part_id is null) then 
         new.base_Part_id =  0 ;
    if (new.child_count is null) then 
         new.child_count =  0 ;
    if (new.location is null)  then   -- Вполне достаточно для обеспечения последовательного размещения элементов
 
         new.location = GEN_ID(Part_id_gen,  1 );  -- при перемещении между уровнями можно просто сбросить значение Location
 
  end

  if ((inserting) or
      (updating and
       (old.Base_Part_ID <> new.Base_Part_ID)
         )) then    -- Увеличить счетчик детей у нового родителя
 
          UPDATE Part T SET T.CHILD_COUNT=T.CHILD_COUNT+ 1 
            WHERE T.Part_ID = new.Base_Part_ID;

  if ((deleting) or
      (updating and
        (old.Base_Part_ID <> new.Base_Part_ID)
          )) then    -- Уменьшить счетчик детей у старого родителя
 
        UPDATE Part T SET T.CHILD_COUNT=T.CHILD_COUNT- 1 
          WHERE T.Part_ID = old.Base_Part_ID;

  if (deleting) then  -- Каскадное удаление. Если не требуется, то перекрывается на клиенте
 
      delete from Part T 
        where
          T.base_Part_id = OLD.Part_id;
END
^
...

SET TERM ; ^



 /*************/ 
 /* Процедуры */ 
 /*************/ 

CREATE PROCEDURE GET_TREE_PART (
    MASTER_PART_ID INTEGER)
RETURNS (
    PART_ID INTEGER,
    TYPE_BILL_ID INTEGER,
    MAIN_PART_ID INTEGER,
    UNIT_ID INTEGER,
    DEPARTMENT_ID INTEGER,
    PART_CATEGORY_ID INTEGER,
    BASE_PART_ID INTEGER,
    POINTER_PART_ID INTEGER,
    REG_DATE DATE,
    REG_TIME TIME,
    FNAME_SHORT VARCHAR( 84 ),
    FNAME VARCHAR( 150 ),
    COMMENT VARCHAR( 250 ),
    BOOLEAN_GOODS_OR_SERVICE INTEGER,
    VERSION_CODE VARCHAR( 250 ),
    VERSION_BUILD VARCHAR( 250 ),
    SUMMA_PRICE NUMERIC( 12 , 2 ),
    QUANTITY NUMERIC( 14 , 4 ),
    QUANTITY_TOTAL NUMERIC( 14 , 4 ),
    SUMMA_NO_TAX_RATE NUMERIC( 12 , 2 ),
    PC_TAX_RATE NUMERIC( 12 , 4 ),
    SUMMA_TAX_RATE NUMERIC( 12 , 2 ),
    SUMMA NUMERIC( 12 , 2 ),
    NODE_CATEGORY VARCHAR( 6 ),
    BOOLEAN_PART_OR_REFERENCE INTEGER,
    LOCATION INTEGER,
    CHILD_COUNT INTEGER)
AS
begin
  for select part_id, type_bill_id, main_part_id, unit_id, department_id, part_category_id, base_part_id, pointer_part_id, reg_date, reg_time, fname_short, fname, comment, boolean_goods_or_service, version_code, version_build, summa_price, quantity, quantity_total, summa_no_tax_rate, pc_tax_rate, summa_tax_rate, summa, node_category, boolean_part_or_reference, location, child_count
  from Part T
  where Base_Part_id =:MASTER_Part_id
  order by T.Location, T.FName_Short
  into :part_id, :type_bill_id, :main_part_id, :unit_id, :department_id, :part_category_id, :base_part_id, :pointer_part_id, :reg_date, :reg_time, :fname_short, :fname, :comment, :boolean_goods_or_service, :version_code, :version_build, :summa_price, :quantity, :quantity_total, :summa_no_tax_rate, :pc_tax_rate, :summa_tax_rate, :summa, :node_category, :boolean_part_or_reference, :location, :child_count
   do begin
     suspend;
     if (Child_Count >  0 ) then
       for  select part_id, type_bill_id, main_part_id, unit_id, department_id, part_category_id, base_part_id, pointer_part_id, reg_date, reg_time, fname_short, fname, comment, boolean_goods_or_service, version_code, version_build, summa_price, quantity, quantity_total, summa_no_tax_rate, pc_tax_rate, summa_tax_rate, summa, node_category, boolean_part_or_reference, location, child_count
       from get_tree_part(:Part_id)
       into :part_id, :type_bill_id, :main_part_id, :unit_id, :department_id, :part_category_id, :base_part_id, :pointer_part_id, :reg_date, :reg_time, :fname_short, :fname, :comment, :boolean_goods_or_service, :version_code, :version_build, :summa_price, :quantity, :quantity_total, :summa_no_tax_rate, :pc_tax_rate, :summa_tax_rate, :summa, :node_category, :boolean_part_or_reference, :location, :child_count
     do suspend;
   end
end

 /* Эта процедурка - для контроля против "циклических ссылок" */ 

CREATE PROCEDURE GET_PARENTS_PART (
    ID INTEGER)
RETURNS (
    DID INTEGER,
    OID INTEGER)
AS
BEGIN
  WHILE (ID >  0 ) DO
    BEGIN
      SELECT t.Part_id, t.base_Part_id
      FROM Part T
      WHERE T.Part_id = :ID
      INTO :DID, :OID;
      ID=OID;
      SUSPEND;
    END
END

 /*Домаю, понятно:*/ 

CREATE PROCEDURE RECOUNT_PART (
    ID INTEGER)
AS
begin
  update part  T set
    T.summa = T.summa_price * T.quantity,
    T.summa_tax_rate = T.summa / ( T.pc_tax_rate +  100 ) * T.pc_tax_rate,
    T.summa_no_tax_rate = T.summa - T.summa_tax_rate
  where part_id = :Id;
end

 /*Это - то же самое, но для работы со "ссылками":*/ 

CREATE PROCEDURE RECOUNT_REFERENCES_PART (
    REFERENCES_ID INTEGER)
AS
begin
  update Part  T set
    T.summa = T.summa_price * T.quantity,
    T.summa_tax_rate = T.summa / ( T.pc_tax_rate +  100 ) * T.pc_tax_rate,
    T.summa_no_tax_rate = T.summa - T.summa_tax_rate
  where Part.pointer_Part_id = :references_id;
end

...
Рейтинг: 0 / 0
16.06.2004, 18:06
    #32564323
mv
mv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
Ой, блин, лишку в тексте триггеров удалил, да и совсем не там.
Вот, скорее, так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
 /* Trigger: PART_GEN_ID */ 
CREATE TRIGGER PART_GEN_ID FOR PART
ACTIVE BEFORE INSERT POSITION  0 
as
begin 
    IF (new.Part_id IS NULL) THEN
       new.Part_id = GEN_ID(Part_id_gen,  1 );
end
^

 /* Trigger: PART_POINTER_AD */ 
CREATE TRIGGER PART_POINTER_AD FOR PART
ACTIVE AFTER DELETE POSITION  0 
AS
 /* При удалении детали
  удалять и соответсвующие детали пакетов */ 
BEGIN
  if (old.boolean_part_or_reference =  0 ) then
  begin
    delete from Part
    where Part.pointer_Part_id =
          old.Part_id;
  end
END
^

 /* Trigger: PART_POINTER_BU */ 
CREATE TRIGGER PART_POINTER_BU FOR PART
ACTIVE BEFORE UPDATE POSITION  0 
AS
 /* При изменении детали изменять и 
   соотв. детали пакетов*/ 
BEGIN
 /* При изменении детали изменять и 
   соотв. детали пакетов*/ 
 /* Если это не перемещение...*/ 
if ((new.Part_id = old.Part_id)
   and ((old.node_category = 'Лист')
      or(old.node_category = 'Пакет'))
   and (old.boolean_part_or_reference =  0 ))  then begin

 /* Если есть ссылки на элемент*/ 
  if (exists (select Part_id from Part
               where Part.pointer_Part_id = old.Part_id)) then
  begin

   /* Переносим Код вида счета */ 
    if ((old.type_bill_id <> new.type_bill_id)
     or (old.type_bill_id is not null) and
        (new.type_bill_id is null)
     or (old.type_bill_id is null) and
        (new.type_bill_id is not null)) then begin
      update Part set type_bill_id = new.type_bill_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код главной номенклатуры */ 
    if ((old.main_part_id <> new.main_part_id)
     or (old.main_part_id is not null) and
        (new.main_part_id is null)
     or (old.main_part_id is null) and
        (new.main_part_id is not null)) then begin
      update Part set main_part_id = new.main_part_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код ед измер */ 
    if ((old.unit_id <> new.unit_id)
     or (old.unit_id is not null) and
        (new.unit_id is null)
     or (old.unit_id is null) and
        (new.unit_id is not null)) then begin
      update Part set unit_id = new.unit_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код подразделения */ 
    if ((old.department_id <> new.department_id)
     or (old.department_id is not null) and
        (new.department_id is null)
     or (old.department_id is null) and
        (new.department_id is not null)) then begin
      update Part set department_id = new.department_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код категории товара */ 
    if ((old.part_category_id <> new.part_category_id)
     or (old.part_category_id is not null) and
        (new.part_category_id is null)
     or (old.part_category_id is null) and
        (new.part_category_id is not null)) then begin
      update Part set part_category_id = new.part_category_id
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Полн. наименование */ 
    if ((old.fname_short <> new.fname_short)
     or (old.fname_short is not null) and
        (new.fname_short is null)
     or (old.fname_short is null) and
        (new.fname_short is not null)) then begin
      update Part set fname_short = new.fname_short
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Полное наименование */ 
    if ((old.fname <> new.fname)
     or (old.fname is not null) and
        (new.fname is null)
     or (old.fname is null) and
        (new.fname is not null)) then begin
      update Part set fname = new.fname
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Товар/Услуга */ 
    if ((old.boolean_goods_or_service <> new.boolean_goods_or_service)
     or (old.boolean_goods_or_service is not null) and
        (new.boolean_goods_or_service is null)
     or (old.boolean_goods_or_service is null) and
        (new.boolean_goods_or_service is not null)) then begin
      update Part set boolean_goods_or_service = new.boolean_goods_or_service
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Код версии */ 
    if ((old.version_code <> new.version_code)
     or (old.version_code is not null) and
        (new.version_code is null)
     or (old.version_code is null) and
        (new.version_code is not null)) then begin
      update Part set version_code = new.version_code
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Сборка */ 
    if ((old.version_build <> new.version_build)
     or (old.version_build is not null) and
        (new.version_build is null)
     or (old.version_build is null) and
        (new.version_build is not null)) then begin
      update Part set version_build = new.version_build
      where old.Part_id = Part.pointer_Part_id;
      
    end

 /* Переносим Цена */ 
    if ((old.summa_price <> new.summa_price)
     or (old.summa_price is not null) and
        (new.summa_price is null)
     or (old.summa_price is null) and
        (new.summa_price is not null)) then begin
      update Part set summa_price = new.summa_price
      where old.Part_id = Part.pointer_Part_id;
      execute procedure recount_references_Part(old.Part_id); 

    end

 /* Переносим Ставка налога, % */ 
    if ((old.pc_tax_rate <> new.pc_tax_rate)
     or (old.pc_tax_rate is not null) and
        (new.pc_tax_rate is null)
     or (old.pc_tax_rate is null) and
        (new.pc_tax_rate is not null)) then begin
      update Part set pc_tax_rate = new.pc_tax_rate
      where old.Part_id = Part.pointer_Part_id;
      execute procedure recount_references_Part(old.Part_id); 

    end



  end
end
END
^

 /* Trigger: PART_QUANTITY_ADD */ 
CREATE TRIGGER PART_QUANTITY_ADD FOR PART
ACTIVE BEFORE INSERT POSITION  2 
as
declare variable P_Node_Category VARCHAR( 6 );
declare variable P_Quantity_Total NUMERIC ( 14 , 4 );
declare variable Koeff NUMERIC ( 14 , 4 );
declare variable P_Boolean_Part_Or_Reference INTEGER;


BEGIN
   /* Добавление: если добавляем не ссылку, а лист или пакет, то
     посмотреть количество у родителя, и,
     если он пакет, и умножить количество родителя на текущее количество */ 
  Koeff =  1 ;
  if ((new.Node_Category IN  ('Лист', 'Пакет')) 
  and (new.BASE_Part_ID >  0 )
  and (new.Boolean_Part_Or_Reference =  0 )
) then begin
    select Node_Category, 
  Boolean_Part_Or_Reference,
Quantity_Total from Part T
      where T.Part_ID = new.BASE_Part_ID into
      P_Node_Category,
  P_Boolean_Part_Or_Reference,
      P_Quantity_Total;
    if ((P_Node_category = 'Пакет') 
  and (P_Boolean_Part_Or_Reference =  0 )

) then
        Koeff = P_Quantity_Total; 
  end
  new.Quantity_Total = new.Quantity * Koeff; 

END
^

 /* Trigger: PART_QUANTITY_UPD */ 
CREATE TRIGGER PART_QUANTITY_UPD FOR PART
ACTIVE BEFORE UPDATE POSITION  2 
as
declare variable P_Node_Category VARCHAR( 6 );
declare variable P_Quantity_Total NUMERIC ( 14 , 4 );
declare variable Koeff NUMERIC ( 14 , 4 );
declare variable P_Boolean_Part_Or_Reference INTEGER;

BEGIN    
   /* Узел-не-ссылка-и-(лист или пакет) переместился или изменилось количество: то
   посмотреть общее количество у родителя, и,
   если родитель пакет, получить новое общее количество, умножив общее количество родителя на текущее количество */ 
  Koeff =  1 ;
  if ((new.Node_Category IN  ('Лист', 'Пакет')) 
    and (new.Boolean_Part_Or_Reference =  0 )


) then begin

    if ((old.Base_Part_ID <> new.Base_Part_ID) 
      or(old.Quantity <> new.Quantity) ) then begin  /* Перемещение */ 
      if (new.BASE_Part_ID >  0 ) then begin
        select Node_Category, 
        Boolean_Part_Or_Reference,

        Quantity_Total from Part T
          where (T.Part_ID = new.BASE_Part_ID) into
          P_Node_Category, 
          P_Boolean_Part_Or_Reference,

          P_Quantity_Total;
        if ((P_Node_category = 'Пакет') 
        and (P_Boolean_Part_Or_Reference =  0 )


      ) then
          Koeff = P_Quantity_Total; 
      end   
      new.Quantity_Total = new.Quantity * Koeff; 
    end

    if ((new.Quantity_Total <> old.Quantity_Total) 
    and (new.Node_Category = 'Пакет')) then
      update Part T set 
        T.Quantity_Total = T.Quantity * new.Quantity_Total
        where ((T.Base_Part_Id = New.Part_Id) 
         and  (T.Node_Category IN  ('Лист', 'Пакет')) 
        and (T.Boolean_Part_Or_Reference =  0 )


); 
  end
END
^

 /* Trigger: PART_SUMM_ADD */ 
CREATE TRIGGER PART_SUMM_ADD FOR PART
ACTIVE BEFORE INSERT POSITION  2 
as
BEGIN    
  if ((new.base_Part_id >  0 ) and (new.summa <>  0 )) then begin
     /* Если от чего-то наследуется, родителю передать сумму*/ 
    update Part T set
      T.summa_price = T.summa_price + new.summa
      where T.Part_id = new.base_Part_id;
    execute procedure recount_Part(new.base_Part_id);
  end
END
^

 /* Trigger: PART_SUMM_DEL */ 
CREATE TRIGGER PART_SUMM_DEL FOR PART
ACTIVE BEFORE DELETE POSITION  2 
as
BEGIN    
  if ((old.base_Part_id >  0 ) and (old.summa <>  0 )) then begin
   /* Если от чего-то наследовался, у родителя вычесть сумму*/ 
    update Part T set
      T.summa_price = T.summa_price - old.summa
      where T.Part_id = old.base_Part_id;
    execute procedure recount_Part(old.base_Part_id);
  end
END
^

 /* Trigger: PART_SUMM_UPD */ 
CREATE TRIGGER PART_SUMM_UPD FOR PART
ACTIVE BEFORE UPDATE POSITION  2 
as
BEGIN    
  if ((old.base_Part_id >  0 ) and (old.summa <>  0 )) then begin
   /* Если от чего-то наследовался, у бывшего родителя вычесть сумму*/ 
    update Part T set
      T.summa_price = T.summa_price - old.summa
      where T.Part_id = old.base_Part_id;
    execute procedure recount_Part(old.base_Part_id);
  end
  if ((new.base_Part_id >  0 ) and (new.summa <>  0 )) then begin
   /* Если будет от чего-то наследоваться, новому родителю передать сумму*/ 
    update Part T set
      T.summa_price = T.summa_price + new.summa
      where T.Part_id = new.base_Part_id;
    execute procedure recount_Part(new.base_Part_id);
  end
END
^

 /* Trigger: PART_TREE_BIUD */ 
CREATE TRIGGER PART_TREE_BIUD FOR PART
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION  99 
as
BEGIN    --  Прайс - обеспечение фукционирования как дерева
 
  if (inserting or updating) then begin
    if (new.base_Part_id is null) then 
         new.base_Part_id =  0 ;
    if (new.child_count is null) then 
         new.child_count =  0 ;
    if (new.location is null)  then   -- Вполне достаточно для обеспечения последовательного размещения элементов
 
         new.location = GEN_ID(Part_id_gen,  1 );  -- при перемещении между уровнями можно просто сбросить значение Location
 
  end

  if ((inserting) or
      (updating and
       (old.Base_Part_ID <> new.Base_Part_ID)
         )) then    -- Увеличить счетчик детей у нового родителя
 
          UPDATE Part T SET T.CHILD_COUNT=T.CHILD_COUNT+ 1 
            WHERE T.Part_ID = new.Base_Part_ID;

  if ((deleting) or
      (updating and
        (old.Base_Part_ID <> new.Base_Part_ID)
          )) then    -- Уменьшить счетчик детей у старого родителя
 
        UPDATE Part T SET T.CHILD_COUNT=T.CHILD_COUNT- 1 
          WHERE T.Part_ID = old.Base_Part_ID;

  if (deleting) then  -- Каскадное удаление. Если не требуется, то перекрывается на клиенте
 
      delete from Part T 
        where
          T.base_Part_id = OLD.Part_id;
END
^



...
Рейтинг: 0 / 0
17.06.2004, 10:46
    #32564876
anjey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
слушай, а рука набивать все это не устала ? :)
...
Рейтинг: 0 / 0
17.06.2004, 10:57
    #32564910
mv
mv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
"Паслюшай, дарагой, какой автоматизм - не видишь, все вручную?"

Скрипт автоматически сгенерирован программкой AllFusion ErWin DataModeller . (Ver 4.1.4.3643). Если хочешь, могу проект кинуть.
...
Рейтинг: 0 / 0
18.06.2004, 06:16
    #32566413
Klick
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
блин... алес капут :(
такие посты огроменные. MV, зачем они? ужасть... каким нить прикрепленным файлом нельзя что ли? или по почте меняться с тем кому это надо.
читать невозможно ж...
...
Рейтинг: 0 / 0
16.08.2004, 13:33
    #32650855
affa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
А что полностью весь скрипт сгенерировал ?
Так уж ничего в скриптах руками и не правил ?
...
Рейтинг: 0 / 0
16.08.2004, 18:00
    #32651600
LSV
LSV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
ну и посты.... :(

решений обычно два:
1. В карточке товара строчное поле aaabbbcccddd...
где зашито нахождение в иерархии. Всегда можно получить всю ветку Like 'aaabbb%'. Недостатки - огранич.вложенность, медленные строчные операции и Like.

2. Внешняя таблица с перечислением всего пути от листьев к корню дерева.
Таблица узкая, хотя и очень длинная. Длина сильно зависит от уровня вложености (каждый уровень удваивает таблицу).
Всегда можно 1-м запросом получить все листья любой ветки или подветки. Рулится всё триггерами...Скорость обычно вполне нормальная.
...
Рейтинг: 0 / 0
16.08.2004, 18:10
    #32651629
Серега
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
LSVну и посты.... :(

решений обычно два:
1.
2.
Ну у тебя и решения. 8-)
...
Рейтинг: 0 / 0
01.09.2004, 13:28
    #32675266
roma_tundra
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
в Access 2002
одна таблица, в которой содержаться и группы и записи
id код(текст, нач. с буквы: это для TreeView'a)
name наименование
idParent код родителя
vol уровень группировки

в окне СХЕМА ДАННЫХ заносим табл. Справочник два раза
и привязываем idParent одной табл. к id другой
уровень я сделал, но пока он пригодился только при формирования отчета(типа прайс)
Если надо - вышлю .mde с рабочей(он недоделаной) базой
...
Рейтинг: 0 / 0
01.09.2004, 13:30
    #32675274
roma_tundra
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
построение иерархических справочников
в Access 2002
одна таблица, в которой содержаться и группы и записи
id код(текст, нач. с буквы: это для TreeView'a)
name наименование
idParent код родителя
vol уровень группировки

в окне СХЕМА ДАННЫХ заносим табл. Справочник два раза
и привязываем idParent одной табл. к id другой
уровень я сделал, но пока он пригодился только при формирования отчета(типа прайс)
Если надо - вышлю .mde с рабочей(он недоделаной) базой
...
Рейтинг: 0 / 0
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / построение иерархических справочников / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]