22.09.2007 17:30
Vlad
 
Вот наднях написал триггер который при смене статуса приходной накладной сверяет цены в спецификации с ценами из таблицы smprices, вроде работает, но думаю его можно улучшить, а я незнаю как. Может кто что посоветует?
Вот сам триггер:
Код:
TRIGGER supermag.smspec_ok      
before insert or update 
ON supermag.smdocuments  
for each row 
WHEN (new.doctype='WI' and new.docstate>1)
declare      
	fPrice_raz number(20,4); 
	ART VARCHAR2(50); 
	CENA NUMBER (20,4);  
	I NUMBER(20); 
	I_MAX NUMBER(20); 
	S NUMBER(20);     
begin  
    SELECT MAX(DISPLAYITEM) INTO I_MAX 
    FROM SMSPEC 
    WHERE DOCID=:NEW.ID; 
    FOR I IN 1..I_MAX LOOP 
    S:=I; 
  BEGIN 
	  SELECT (PR.PRICE-SP.ITEMPRICE) raz, SP.ARTICLE, PR.PRICE 
	  INTO fPrice_raz,ART, CENA       
      FROM   SMPRICES PR, 
	         SMSPEC SP        
       WHERE  PR.ARTICLE=SP.ARTICLE      
           AND :new.DOCTYPE='WI'      
	       AND PR.PRICETYPE=1      
	       AND SP.DOCID=:new.ID  
		   AND SP.DOCTYPE=:new.DOCTYPE     
	       AND PR.STORELOC=:NEW.LOCATIONTO 
		   AND SP.DISPLAYITEM=S; 
  EXCEPTION		   	 
  when NO_DATA_FOUND then 
			/*Core.Fail((-20000-56)); 
			RETURN;*/ 
			raise_application_error (-20000,'В документе присутствует новый товар (товар ранее не поставлялся) или неупорядочены строки в накладной (Упорядочить №№'); 
  end;          
  IF fPRICE_RAZ <> 0      
    THEN      
       raise_application_error (-20000,'Неправильная цена у артикула ' || ART || ' она должна быть равна ' || cena); 
    END IF; 
END LOOP; 
END smspec_ok;
23.09.2007 23:50
OlegON
 
Не очень понятно, зачем внутри триггера цикл, если он "for each row", собственно, вообще не понятно, что он делает. У вас приходные и розничные цены одинаковые?
24.09.2007 08:37
Vlad
 
У нас есть вид цены - "Оптовая", эта цена равна цене в прихоной накладной, т. е. наценка на нее 0. Так вот если цена в накладной оличается от того что есть в smspec то накладная не проводится. Цикл for нужен для того чтобы выбирать каждую строку из таблицы smspec, триггер срабатывает при обновлении таблицы smdocuments.
P. s. версия СМ2000 1.23.3 сервис пак 3. Oracle 8.1.6
24.09.2007 10:57
OlegON
 
А если на smspec триггер такой ставить не быстрее получится? Сканить ее не надо будет... А она со временем ого-го какая становится...
24.09.2007 11:36
Vlad
 
На smspec скорей всего неполучится, т. к. эту накладную даже в черновике сохранить не получится. Либо я не догнал еще как такой тригер сделать.
25.09.2007 15:11
slava
 
Не вдаваясь в подробности зачем?
SELECT MAX(DISPLAYITEM) INTO I_MAX
FROM SMSPEC
WHERE DOCID=:NEW.ID;
Посмотри план выполнения!

BEGIN
SELECT (PR.PRICE-SP.ITEMPRICE) raz, SP.ARTICLE, PR.PRICE
INTO fPrice_raz,ART, CENA
FROM SMPRICES PR,
SMSPEC SP
WHERE PR.ARTICLE=SP.ARTICLE
AND :new.DOCTYPE='WI'
^^^^^^^^^^^^^^^
Это TRUE по условию срабатывания триггера
26.09.2007 09:10
Vlad
 
Посмотрел план действительно запрос:
Код:
SELECT MAX(DISPLAYITEM) INTO I_MAX 
FROM SMSPEC 
WHERE DOCID=:NEW.ID;
вызывает Full scan по таблице smspec
переделываем
Код:
SELECT MAX(DISPLAYITEM) INTO I_MAX 
FROM SMSPEC 
WHERE DOCID=:NEW.ID
and doctype=:new.doctype
full scan уже нет
Спасибо, сам бы не посмотрел.
Если возможность сообщение в raise_application_error выводить в несколько строк? А то у меня все в одной строке - неудобно.
Часовой пояс GMT +3, время: 12:20.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.