powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / автоматическая передача программе новых записей
26 сообщений из 26, показаны все 2 страниц
автоматическая передача программе новых записей
    #32026409
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
помогите решить проблему!
есть простенькая прога которая через SQL запрос выбирает данные из элементарной таблички Oracle.
просьба нарисовать пример: как реализовать чтобы Oracle сам инициировал передачу новообразованых записей данных в табличке клиентской проге (пример может быть для проги на C++ или Delphi)
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026450
alvako
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Наверное надо известить клиента о появлении новых записей.
Можно попытаться сделать это из триггера after-insert через DBMS_PIPE или DBMS_ALERT.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026471
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а примера кода нету!!!
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026473
professional
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну вот так, сразу что в голову пришло....
короче можно так:
создать дополнительную таблицу.
на основную таблицу поставить триггер на вставку, так что бы
он сбрасывал все новые записи в доп. таблицу.
а из делфи при помощи таймера постоянно обращаться к новой таблице
(раз в минуту например) и в случае получения записей считывать их и удалять...
(ну это самый простой пример, его может сделать любой я уверен что и ты
без всякой помощи его сделаешь)
если не устроит тебя такой ответ то дай знать,
может че другое в голову придет..
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026490
alvako
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 AlexG
Читай документацию - там тебе и примеры будут.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026493
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
про временную табличку мне сразу идея пришла, но это опять же - необходимо клиентской проге к Oracle периодически стукать, что крайне режелательно (что-то проскакивало в соседних конфах по ADO на счёт авто обновления по поводу новых записей для MS васика и С++ - киньте примером или ссылкой на исходняк если таковые у вас есть люди добрые)!!!
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026524
super professional
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
короче лучший вариант в это случае сделать так:
опять таки как говорил professional создать триггер на вставку записей...

затем написать DLL и подключить ее на сервере,
которая будет собирать информацию о вставленных записях и затем
будет передавать их клиеету
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026554
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
зачем городить какие-то Dll. чем не устраивает DBMS_PIPE/DBMS_ALERT?
сначала говоришь серверу что хочешь получать сообшения, потом в тригер AFTER UPDATE и/или AFTER INSERT ставишь
посылку сообщения через DBMS_PIPE/DBMS_ALERT (в данном случае, на мой взгляд, лучше использовать DBMS_ALERT),
программа получает это сообщение и обновляет данные. Я именно так и делаю.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026557
alvako
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Единственная проблема которая может в данном случае возникнуть при использовании DBMS_PIPE/DBMS_ALERT - это то, что данный механизм межпроцессных коммуникации нетранзакционный. Т.е. срабатывать из триггера и оповещать клиента он будет после insert-a записей независимо от того зафиксирована была транзакция или была откатана.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026558
alvako
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
+ клиент может полезть в базу за обновлениями до того как они будут зафиксированы.
таким образом делать оповещение через DBMS_PIPE/DBMS_ALERT надо не из триггера post-insert а из программы которая добавляет запись, причём непосредственно после commit.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026569
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
4 alvako
Ты не прав(точнее не совсем прав). DBMS_ALERT посылает сообщение только после коммита, это ее одно из отличий от DBMS_PIPE. Поэтому я и сказал что в данном случае надо ее использовать.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026570
alvako
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Точно "Alerts are asynchronous and transaction-based". Я почему-то думал что у них с pipe-ми одна природа.
Тогда вообще нет ни каких проблем.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026778
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1 nick
ну если "я так и делаю", то скинь наконец фрагмент кода (небольшой
) как именно ты это делаешь...
через DBMS_ALERT разумеется!
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026779
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
create or replace trigger mytrigger
after insert or update or delete on mytable
begin
DBMS_ALERT.SIGNAL('myevent','Пора обновиться');
end;

Обработка зависит от того, что ты используешь. Я использую DOA, примерно так же будет и при использование ODAC.
procedure TfrmMain.OracleEventEvent(Sender: TOracleEvent;
const ObjectName: String; const Info: Variant);
begin
// обновление данных;
end;

OracleEvent.ObjectNames='myevent';
OracleEvent.ObjectType:=otAlert;
OracleEvent.OnEvent:=TfrmMain.OracleEventEvent;
OracleEvent.Start;
Извини, но больше нечего писать, поэтому и не приводил ни каких примеров. Слишком все просто.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026830
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
3 nick

спасибо! буду пробовать использовать.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026946
mmoroz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я пробовал использовать DBMS_ALERT (поскольку он транзаксозависимый), но там такая неудобная штука:
когда происходит изменение он посылает сигнал всем сессиям которые его в ДАННЫЙ МОМЕНТ СЛУШАЮТ. Если прцесс прослушки не запущен, то данное изменение для этой сесии считается потрянным. Т.е. чтобы с DBMS_ALERT работало надо чтобы на клиенте ПОСТОЯННО болтался прослушивающий процесс. По идее надо создать пул этих процессов работающих параллельно и пока одни процессы обрабатывают поступившее сообщение другие ожидают следующих. Мне все это показалось достаточно громоздким (может я неправ, хотя сроки поджимали) и поэтому был реализован вариант триггера с временной таблицей. клиент периодически ее опрашивает.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32026996
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
for mmoroz
а что висячий таймер лучше висячего alert'а?
и через кокое время делать никому не нужный селект (из временной таблице, и при плохой связи)?
мне кажестя вы совсем не разобрались. можно же передавать не только факт изменения таблицы, но и сами изменения
(или их часть).
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027033
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
for mmoroz
это же логично: ипользовать DBMS_ALERT для "активного" мониторинга БД, то есть подключился и ловишь данные на лету, а отключился - они просто пишутся в БД, возможно во временную таблицу - которую ты прочитаешь и очистишь при следующем подключении, идальше включаешь "мониторинг".

for nick
а каким макаром ты передаёшь новую строку программе, склеиваешь через разделитель или ещё как? есть DBMS_UTILITY.TABLE_TO_COMMA и назад , но как быть с дробными числами и BLOB полями (может DBMS_PIPE пристроить как-то)?!
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027051
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
for AlexG
всю строку я не передаю, но могу, правда не со всеми полями
(на сообшение накладывается ограничение по размеру 1800байт и типу данных - должна быть строка).
я обычно передаю какой-нибудь идентификатор, а станция решает нужно ей обновлять данные или нет.
например:
пользователь просматривает документы за 1.01.2002, а изменения произошли в документах за 2.01.2002
тогда я передаю в качестве идентификатора дату и станция решает, что ей эти изменения не нужны.

передавать данные можно как в INI файлах
variable1=value1
variable2=value2

DBMS_PIPE сдесь скорее всего не помошник. он передает данные в не зависимости от транзакций.

есть правда вариант после прихода сообщения включать дополнительный слушатель и ждать "дополнительную информацию",
в которой передавать (возможно в несколько заходов) всю информацию.
при таком подходе можно использовать и DBMS_PIPE и DBMS_ALERT, но мне кажется это слишком сложно и с отладкой замучеешься.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027088
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
к стати возникает паралельная проблема:

написал две програмы одна дописывает данные вторая показывает обновления,
сервер на другой машине ...
на 10 записей программа "ловит" 7-8 алертов в лучшем случае, осальное в "воздух"
прямо не "он-лайн мониторинг", "дуршлаг" какой-то
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027094
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
это может происходить если во время прихода сообщения твоя программа обрабатывает предыдущее.
чтобы этого не происходило, сразу после принятия сообщения создавай нить и уже в ней обновляй данные.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027095
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
to nick
учту!

to All

к стати тут начал активно юзать DOA, а он подлый (стянутый из и-нета) матерится на других машинах, что "EVALUTION COPY NEED DELPHI" - помогите люди добрые!!!!!!!
может у кого "халява есть"?
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027098
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
http://dx7e9ws.narod.ru/
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027102
AlexG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
to nick

переписал компоненты... не помогает!
может в регистрах инсталяшка что-то прописала?
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32027147
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я сам пользуюсть тем, что скачал с этого сервера. у меня все сразу заработало, поэтому ничего не могу подсказать.
...
Рейтинг: 0 / 0
автоматическая передача программе новых записей
    #32048653
Nguyen Quang Trung
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
try this, I used NCOCI8
not very good but work, U can do some more customize

******************************************
//OraAlert.pas
******************************************
unit OraAlert;

interface
uses Windows,Classes,sysutils,Db,NCOci, NCOciWrapper, NCOciDB, NCOciParams;
type

TDbmsAlertEvent = procedure(Sender: TObject; msg: string) of object;
TErrorEvent = procedure(Sender: TObject; err: exception) of object;

TOraAlert = class(TThread)
private
FOwner:TComponent;
FDatabase:TOCIDatabase;
FSPRRegister:TOCIStoredProc;
FSPRWaitone:TOCIStoredProc;
FOnAlert:TDbmsAlertEvent;
FOnTimeOut:TNotifyEvent;
FOnError:TErrorEvent;
FOnStart:TNotifyEvent;
FOnStop:TNotifyEvent;
FEventName:string;
FTimeOut:integer;
FStarted:boolean;
FServerName:string;
FUserName:string;
FPassword:string;
protected
procedure ProcessMsg;
procedure Execute;override;
procedure DoAlertEvent(msg:string);
procedure DoTimeoutEvent;
procedure DoStartEvent;
procedure DoStopEvent;
procedure DoErrorEvent(err:exception);
procedure SetEventName(ename:string);
procedure SetTimeOut(tout:integer);
procedure PrepareStoreProcs;
public
constructor Create(AOwner:TComponent;dbname:string);
destructor Destroy;override;
procedure Logon;
procedure Logoff;
procedure Start;
procedure Stop;
published
property ServerName:string read FServerName write FServerName;
property UserName:string read FUserName write FUserName;
property Password:string read FPassword write FPassword;
property EventName:string read FEventName write SetEventName;
property TimeOut:integer read FTimeOut write SetTimeOut;
property Started:boolean read FStarted write FStarted;
property OnAlert:TDbmsAlertEvent read FOnAlert write FOnAlert;
property OnStart:TNotifyEvent read FOnStart write FOnStart;
property OnStop:TNotifyEvent read FOnStop write FOnStop;
property OnTimeOut:TNotifyEvent read FOnTimeOut write FOnTimeOut;
property OnError:TErrorEvent read FOnError write FOnError;
end;

implementation

constructor TOraAlert.Create(AOwner:TComponent;dbname:string);
begin
{TODO: Create new TOraAlert instant here}
inherited Create(true);
FOwner:=AOwner;
FreeOnTerminate:=false;
Priority:=tpLower;
FDatabase:=TOCIDatabase.Create(nil);
FDatabase.Name:='odbAlert';
FDatabase.DatabaseName:=dbname;
FDatabase.LoginPrompt:=false;
FSPRRegister:=TOCIStoredProc.Create(nil);
FSPRRegister.Name:='sprRegister';
FSPRRegister.DatabaseName:=FDatabase.DatabaseName;
FSPRWaitone:=TOCIStoredProc.Create(nil);
FSPRWaitone.Name:='sprWaitone';
FSPRWaitone.DatabaseName:=FDatabase.DatabaseName;
FTimeout:=0;
FEventName:='';
end;

destructor TOraAlert.Destroy;
begin
DoStopEvent;
suspend;
FSPRRegister.Free;
FSPRWaitone.Free;
FDatabase.Free;
inherited Destroy;
end;

procedure TOraAlert.Logon;
begin
FDatabase.UserName:=FUserName;
FDatabase.ServerName:=FServerName;
FDatabase.Password:=FPassword;
FDatabase.Connected:=true;
if not FDatabase.Connected then exit;
PrepareStoreProcs;
end;

procedure TOraAlert.Logoff;
begin
DoStopEvent;
suspend;
FDatabase.Connected:=false;
end;

procedure TOraAlert.PrepareStoreProcs;
begin
FSPRRegister.StoredProcName:='DBMS_ALERT.REGISTER';
FSPRRegister.Params.Clear;
FSPRRegister.Params.CreateParam(ftString,'NAME',ptInput);
FSPRRegister.ParamByName('NAME').Value:=FEventName;
FSPRRegister.Prepare;
FSPRRegister.ExecProc;
FSPRWaitone.StoredProcName:='DBMS_ALERT.WAITONE';
FSPRWaitone.Params.Clear;
FSPRWaitone.Params.CreateParam(ftString,'NAME',ptInput);
FSPRWaitone.ParamByName('NAME').Value:=FEventName;
FSPRWaitone.Params.CreateParam(ftString,'MESSAGE',ptOutput);
FSPRWaitone.Params.CreateParam(ftString,'STATUS',ptOutput);
FSPRWaitone.Params.CreateParam(ftInteger,'TIMEOUT',ptInput);
FSPRWaitone.ParamByName('TIMEOUT').Value:=FTimeOut;
FSPRWaitone.Prepare;
end;

procedure TOraAlert.Start;
begin
{TODO:Start TOraAlert here}
DoStartEvent;
resume;
end;

procedure TOraAlert.Stop;
begin
{TODO:Stop TOraAlert here}
DoStopEvent;
suspend;
end;

procedure TOraAlert.ProcessMsg;
begin
if FDatabase.Connected then
begin
try
{
with FSPRRegister do
begin
ExecProc;
end;
}
with FSPRWaitone do
begin
ExecProc;
if ParamByName('STATUS').Value=0 then
DoAlertEvent(ParamByName('MESSAGE').Value)
else
DoTimeoutEvent;
end;
except on e:exception do
DoErrorEvent(e);
end;
end;
end;

procedure TOraAlert.Execute;
begin
{TODO: Execute TOraAlert here}
while not Terminated do
begin
ProcessMsg;
sleepex(1,true);
end;
end;

procedure TOraAlert.DoAlertEvent(msg:string);
begin
{TODO:}
if Assigned(FOnAlert) then
FOnAlert(nil,msg);
end;

procedure TOraAlert.DoTimeoutEvent;
begin
{TODO:}
if Assigned(FOnTimeout) then
FOnTimeout(nil);
end;

procedure TOraAlert.DoStartEvent;
begin
{TODO:}
if Assigned(FOnStart) then
FOnStart(nil);
end;

procedure TOraAlert.DoStopEvent;
begin
{TODO:}
if Assigned(FOnStop) then
FOnStop(nil);
end;

procedure TOraAlert.DoErrorEvent(err:exception);
begin
{TODO:}
if Assigned(FOnError) then
FOnError(nil,err);
end;

procedure TOraAlert.SetEventName(ename:string);
begin
{TODO:}
FEventName:=ename;
end;

procedure TOraAlert.SetTimeOut(tout:integer);
begin
{TODO:}
if tout>=0 then
FTimeOut:=tout;
end;


end.

******************************************
//OraAlertDemoMain.pas
******************************************
unit OraAlertDemoMain;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, StdCtrls, NCOci, NCOciWrapper, NCOciDB, OraAlert,
ExtCtrls;

type
TfrmMain = class(TForm)
mmoAlerts: TMemo;
pnlBottom: TPanel;
bttnStart: TButton;
edtEventname: TEdit;
Label1: TLabel;
Label2: TLabel;
edtServername: TEdit;
Label3: TLabel;
edtUsername: TEdit;
Label4: TLabel;
edtPassword: TEdit;
procedure bttnStartClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
oa:TOraAlert;
iCounter:integer;
procedure PaintMemo(Sender: TObject; msg: string);
public
{ Public declarations }
end;

var
frmMain: TfrmMain;

implementation

{$R *.DFM}

procedure TfrmMain.PaintMemo(Sender: TObject; msg: string);
begin
inc(iCounter);
mmoAlerts.Lines.Add(inttostr(iCounter)+'> '+msg);
end;

procedure TfrmMain.bttnStartClick(Sender: TObject);
begin
bttnStart.Enabled:=false;
oa:=TOraAlert.Create(self,'dba1');
oa.ServerName:=edtServername.Text;
oa.UserName:=edtUsername.Text;
oa.Password:=edtPassword.Text;
oa.EventName:=edtEventname.Text;
oa.TimeOut:=10000;
oa.OnAlert:=PaintMemo;
oa.Logon;
oa.Start;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
iCounter:=0;
end;

end.
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / автоматическая передача программе новых записей
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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