![]() |
|
|
#1
|
|||
|
|||
|
Помогите пожалуйста. есть две таблицы ostatki, potrebnost
таблицы ostatki, potrebnost имеют поля (diametr, gost , ves). Нужно если diametr и gost в одной таблице равны diametr и gost в другой то ves из одной таблице должен вычитаться из другой и записыватся в поле itog. Вот текст. Подскажите ,что не так Код:
procedure TForm1.Button2Click(Sender: TObject); begin form1.ADOtable1.first; while form1.ADOtable1.Eof do begin if (ADOtable1diametr.Value=form1.ADOtable2diametr1.Value)and (ADOtable1gost.Value= ADOtable2gost1.Value) then // ADOtable1rezult.Value:=ADOtable2ves1.Value-ADOtable1ves.Value ; ADOtable1itog.Value:=ADOtable2ves1.Value - ADOtable1ves.Value; form1.ADOtable1.next; end;end; Спасибо за помощь Последний раз редактировалось Admin, 26.10.2011 в 18:52. |
|
#2
|
|||
|
|||
|
А на уровне SQL это нельзя сделать?
Код:
select o.diametr, o.gost, (o.ves - p.ves) as itog from ostatki o left join potrebnost p on o.gost=p.gost and o.diametr = з.diametr |
|
#3
|
|||
|
|||
|
есть 2 подхода
1. на уровне SQL- пишешь SQL процедуру 2. на уровне пользовательской подключаемой библиотеки вечером покажу. |
|
#4
|
|||
|
|||
|
/*---вот объявление функций пользователя.
Это оформляется в виде 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'; Теперь о втором способе. Можно в самой БД создать некое свойство, которое позволяет прямо по ходу дела анализировать ситуацию и соответственно ее обрабатывать. Это триггеры- специальные процедуры, внедренные в базу данных и запускающиеся автомтически при наступлении определенных событий в БД. Например, процедура 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 следует помещать функции сложные. Они пишутся на языках высокого уровня и потому просты в отладке. Оформмять твои специфические функции как триггеры следует тогда, когда они достаточно просты и кроме того предвидится необходимость их изменять. Это так называемые Бизнес-правила. Например, как триггер следует оформить функцию вычета подоходного налогга. Если правила исчисления подоходного налога изменились- ты просто в твоей БД изменяешь эту функцию- и она автоматически действует для всех пользователей. */ |
|
#5
|
|||
|
|||
|
Тов, Чайник, а вам не кажется, что вас нетуда понесло???
|