Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: xinyiman - Febbraio 16, 2014, 09:59:46 pm

Titolo: Allineare tabelle
Inserito da: xinyiman - Febbraio 16, 2014, 09:59:46 pm
Ciao ragazzi, ho il seguente problema.

Ho due database residenti su macchine diverse e voglio allineare una di queste tabelle. Chiamiato i due database come: db1 e db2 e le tabelle come tab1 e tab2 (ovviamente tab1 e tab2 hanno la stessa struttura ma hanno database diversi).

Ora per evitare di cancellare i dati tutte le volte da tab2 e ricopiarli da tab1 vorrei cancellare e reinserire le righe che davvero vengono modificate).

Mi basta un trigger per le righe inserite o modificate. Ma per le righe cancellate come posso fare? Vorrei evitare di dover cancellarle solo logicalmente.

Suggerimenti?

Grazie mille
Titolo: Re:Allineare tabelle
Inserito da: Stilgar - Febbraio 17, 2014, 09:33:05 am
Che Engine usi?

Stilgar
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 17, 2014, 02:30:44 pm
Io uso Firebird
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 17, 2014, 03:39:27 pm
devi fare una tabella di log per le eliminazioni

a dire il vero io farei una tabella di log per tutto: insert, update e delete con tanto di progressivo (come PK) per riproporre le sequenza.
nel database di destinazione ti devi segnare l'ultimo progressivo eseguito così alla prossima sincronizzazione riprendi da li.
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 17, 2014, 04:58:27 pm
devi fare una tabella di log per le eliminazioni

a dire il vero io farei una tabella di log per tutto: insert, update e delete con tanto di progressivo (come PK) per riproporre le sequenza.
nel database di destinazione ti devi segnare l'ultimo progressivo eseguito così alla prossima sincronizzazione riprendi da li.

Idea che mi era già frullata in testa. Solo che io quei dati li modifico da una dbgrid e quindi mi rimane difficile da gestire come dici tu. In quanto modificando da tabella non uso delle query da inserire nella tabella di log, e le mie tabelle da allineare hanno PK composte diverse da tabella a tabella.
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 17, 2014, 07:00:15 pm
il log bisognerebbe gestirlo con un trigger direttamente dentro il database
per quanto riguarda le chiavi composte diverse da tabella a tabella potresti fare così:

1) tabella LOG_MASTER (campi: (1) PK autoincrementale (2) nome tabella di cui si deve replicare il record)
2) tabella LOG_DETAIL_TABLE1 (campo (1) FK autoincrementale  (2..) n. campi come da chiave composta per TABLE 1)
3) tabella LOG_DETAIL_TABLE2 (campo (1) FK autoincrementale  (2..) n. campi come da chiave composta per TABLE 2)
4) tabella LOG_DETAIL_TABLEN (campo (1) FK autoincrementale  (2..) n. campi come da chiave composta per TABLE N)

Nelle tabelle detail, ad esempio TABLE 1, nel trigger after insert, update e delete, fai in inserimento in LOG_MASTER ed uno in LOG_DETAIL_TABLEx

Non è sicuramente una struttura facile, ma dovrebbe essere sufficientemente elastica.
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 18, 2014, 03:58:05 pm
Mi sa che mi richiede più fatica che non cancellarlo logicamente.

Per caso altre idee?!
Titolo: Re:Allineare tabelle
Inserito da: Stilgar - Febbraio 19, 2014, 01:15:21 am
Idee che mi vengono al volo.
1)
DELETE * FROM TARGET_TABLE;
SELECT * FROM SOURCE_TABLE;
ALTER TABLE TARGET_TABLE DROP INDEX ....
ALTER TABLE TARGET_TABLE DROP CONSTRAINT ....
Per ogni riga estratta...

INSERT (...) INTO TARGET_TABLE VALUES(...);

Alla fine:
ALTER TABLE TARGET_TABLE ADD CONSTRAINT ....
CREATE INDEX ON TARGET_TABLE ....

Lunghetto e noioso da fare tutto a mano ... :(

Con oracle esistono altri sistemi. Più "eleganti". E si arrangia il motore sql ;)
TRUNCATE TARGET_SCHEMA.TARGET_TABLE;
INSERT INTO TARGET_SCHEMA.TARGET_TABLE VALUE(SELECT * FROM SOURCE_SCHEMA.SOURCE_TABLE);
(Prima devi anche disabilitare gli indici e constraint, in modo che l'insert sia più rapido, poi attivi tutti i costraint e gli indici alla fine... trucchetti da datawarehose).

Firebird non so se supporti questo tipo di sintassi.

E' una logica stupida e va contro la tua richiesta. Ma è quella più semplice da realizzare.
In una banca di cui non ti dico il nome, il riversare i dati da una tabella all'altra era "veloce".
Quando attivavi gli indici si "inchiodava" Oracle ... le cpu schizzavano al 90% .. e stiamo parlando di macchinine di una certa potenza di calcolo. AIX o Solaris dentro Mainframe. ;)
2
(2.1)L'alternativa è tracciare quello che fa l'utente sulla tabella.
Aggiungere un campo con uno "stato". Modificato, Inserito, Cancellato.
Ma poi è una noce lavorare in modo ordinario sulle righe.

Valuta tu.
Questa operazione di ribaltamento deve essere fatta ad ogni operazione o sporadicamente.
(2.2)Nel secondo caso ranza la tabella e caccia tutto dentro senza tante remore.
Se anche ci mette un'oretta (ammesso che la tabella sia molto "piena") l'utente aspetta.

E' un'operazione da fare ad ogni transazione?
Allora l'applicativo deve eseguire le modifiche su entrambe le tabelle.
Configura gli alias e le connessioni in modo fa eseguire una sorta di "raid" se fossero dischi. ;)

3)
Poi anche un export su file ed un import poi, potrebbe essere una soluzione.
Monti una tabella come file csv dalla tabella source.
Copi tutto dentro.
Monti il file come tabella sul db target. Copi tutto dentro sul secondo db.

Poi i file puoi postarli in ftp, per mail, piccione viaggiatore, segnali di fumo. Solo la tua fantasia/pigrizia ti sarà di ostacolo.

Spero di averti confuso le idee più di prima :D

Stilgar
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 19, 2014, 04:09:46 pm
fbexport o fbcopy
http://fbexport.sourceforge.net/ (http://fbexport.sourceforge.net/)

secondo me è meglio che fai con questi ;)
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 19, 2014, 05:37:26 pm
Alla fine mi sono reso conto che o già due campi che mi permettono di rendere il record inutilizabile dal resto del programma. Quindi alla fine li uso come cancellazione logica (così mi mantiene anche una storicità della cosa) e mi gestisco la modifica e l'inserimento con un trigger. Ho perso del tempo inutilmente insomma.

@Stilgar: avevo pensato anche io che gli indici potessero ridurre notevolmente le prestazioni. Farò delle prove e ti dirò al riguardo.
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 19, 2014, 06:23:38 pm
Ora però ho bisogno di capire come renderlo fattibile.

Allora ho creato il campo RECORD_EDIT_INSERT SMALLINT attraverso la query:

ALTER TABLE LISTINO_PREZZI_PV ADD RECORD_EDIT_INSERT SMALLINT default 0 not null;

Poi vado per creare il trigger con la seguente sintassi

Codice: [Seleziona]
CREATE TRIGGER MODIFICA_INSERIMENTO_LISTINI_PV for LISTINO_PREZZI_PV
Active
After insert or update
Position 0
AS
BEGIN
     -- ogni volta che inserisco o
     -- modifico un record vado ad
     -- impostare il campo RECORD_EDIT_INSERT
     -- a 1 in modo che nel trasferire i dati
     -- ai punti vendita io trasferisco solo le
     -- righe essenziali
     -- la cancellazione è bloccata dal programma
     -- semplicemente rendo i record non continuativi
     -- e con la data di inizio vendita e di fine vendita
     -- impostata a 1-1-1900

     new.RECORD_EDIT_INSERT=1;

END;

Applico la creazione del trigger ed è ok, quando però applico la commit retaining mi visualizza questo popup

 : CommitRetaining :
 -attempted update of read-only column

Uso Turbobird, sapete cosa può essere? Dove sbaglio?

Inoltre ho un dubbio amletico: quando poi voglio risettare la colonna RECORD_EDIT_INSERT a 0 come posso fare senza che il trigger entri in funzione?
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 19, 2014, 06:57:37 pm
Inoltre ho un dubbio amletico: quando poi voglio risettare la colonna RECORD_EDIT_INSERT a 0 come posso fare senza che il trigger entri in funzione?

potresti fare la replicazione con una connessione a parte dove ti colleghi con un utente tipo 'XINYREPL'
nel trigger condizioni il codice in modo da essere eseguito solo quando l'utente corrente non è 'XINYREPL'
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 19, 2014, 06:58:50 pm

Applico la creazione del trigger ed è ok, quando però applico la commit retaining mi visualizza questo popup

 : CommitRetaining :
 -attempted update of read-only column


nella tabella fai uso di campi calcolati?
puoi postare la "create table"?
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 19, 2014, 07:16:01 pm
Nessun campo calcolato, ecco la create

create table LISTINO_PREZZI_PV (
CHIAVE_PV CHAR(10)  not null ,
ARTICOLO VARCHAR(50)  not null ,
PREZZO_A Numeric(9,2) ,
PREZZO_V Numeric(9,2) ,
VALUTA_A VARCHAR(20) ,
VALUTA_V VARCHAR(50) ,
IDENTIFICATIVO_LISTINO INTEGER not null ,
CATEGORIA VARCHAR(50) ,
IVA FLOAT,
RAGGRUPPAMENTO_ARTICOLO VARCHAR(255) ,
ORDINE_RAGGRUPPAMENTO_ARTICOLO INTEGER,
DATA_INIZIO_VENDITA DATE,
DATA_FINE_VENDITA DATE,
CONTINUATIVO CHAR(1)  default '0',
ID_CATEG_MERC INTEGER,
UTENTE_MODIFICA_RECORD VARCHAR(255) ,
TIPOLOGIA_PRODOTTO CHAR(1)  default '0',
INFO1 VARCHAR(50) ,
INFO2 VARCHAR(50) ,
INFO3 VARCHAR(50) ,
RECORD_EDIT_INSERT SMALLINT default 0 not null
, constraint IX_LISTINO_PREZZI_PV_1 primary key (CHIAVE_PV, ARTICOLO, IDENTIFICATIVO_LISTINO)
);
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 19, 2014, 07:40:46 pm
non saprei, non ha molto senso
prova a lanciare le stesse istruzioni sql con flamerobin
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 19, 2014, 09:45:43 pm
Con FlameRobin ho provato così:

Codice: [Seleziona]
SET TERM ^ ;

CREATE TRIGGER MODIFICA_INSERIMENTO_LISTINI_PV for LISTINO_PREZZI_PV
Active
After insert or update
Position 0
AS
BEGIN
     -- ogni volta che inserisco o
     -- modifico un record vado ad
     -- impostare il campo RECORD_EDIT_INSERT
     -- a 1 in modo che nel trasferire i dati
     -- ai punti vendita io trasferisco solo le
     -- righe essenziali
     -- la cancellazione è bloccata dal programma
     -- semplicemente rendo i record non continuativi
     -- e con la data di inizio vendita e di fine vendita
     -- impostata a 1-1-1900

     new.RECORD_EDIT_INSERT=1;

END^

SET TERM ; ^
Ma va in loop il programma, si oscura la finestra di flamerobin e non fa nulla. Idee? Inoltre ipotizziamo che ci riesco, come posso poi settare il valore del campo RECORD_EDIT_INSERT a 0 senza che questo cambiamento inneschi nuovamente il trigger e quindi lo riporti automaticamente a 1?
Titolo: Re:Allineare tabelle
Inserito da: Stilgar - Febbraio 20, 2014, 09:29:13 am
Qualche controllo del tipo:
Codice: [Seleziona]
if old.record_edit_insert is null
 new.RECORD_EDIT_INSERT
L'ipotesi è che scatta l'insert, poi l'update. O fanne due.
Uno solo un trigger per le insert e uno solo per gli update ;)

Stilgar
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 20, 2014, 11:15:36 am
Inoltre ipotizziamo che ci riesco, come posso poi settare il valore del campo RECORD_EDIT_INSERT a 0 senza che questo cambiamento inneschi nuovamente il trigger e quindi lo riporti automaticamente a 1?

c'è anche una mia risposta un paio di post fa
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 20, 2014, 04:05:22 pm
Si vista!

Solo che ancora non riesco a capire perchè non mi fa salvare il trigger con la commit. Uffaaaaaaaaaaaa
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 20, 2014, 04:12:22 pm
Sono un coglionazzo. Non posso modificare nell'AFTER devo usare necessariamente il BEFORE.
Titolo: Re:Allineare tabelle
Inserito da: Stilgar - Febbraio 20, 2014, 04:36:02 pm
Basta aver trovato dove sbagliavi.
Il resto è codice :D

Stilgar
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 20, 2014, 05:16:25 pm
Si però fa girare parecchio le pelotas lo stesso  ;)
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 20, 2014, 06:44:03 pm
Qualcuno conosce la sintassi in firebird che disabilita e riabilita gli indici in una tabella?
Titolo: Re:Allineare tabelle
Inserito da: Stilgar - Febbraio 21, 2014, 09:15:07 am
Prova qui a capirci qualche cosa :D

http://www.firebirdfaq.org/faq110/

Stilgar
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 21, 2014, 04:37:04 pm
Ho provato a cancellare l'indice incirminato che mi rende lento l'inserimento. Risultato, non velocizza nulla. Inizio a pensare che firebird su ubuntu abbia qualche difficoltà nell'inserimento di molte righe. Nel mio caso specifico solo 1260 righe.

Inizio: 16:33:12
Fine: 16:34:49

Non ha senso...consigli?
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 21, 2014, 06:44:55 pm
cosa mandi al server, uno script o fai con i ClientDataset?

se è uno script e lo script lo dai in pasto a famerobin quanto ci mette?
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 21, 2014, 07:05:19 pm
al momento un dataset. con una query leggo le righe dal server e poi le scrivo una x una nella tabella in locale. con le insert.
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 22, 2014, 11:10:06 am
ok per la query per leggere i dati (se non erro le query readonly sono anche più veloci).

quando devi fare un inserimento massivo non passare per il dataset se poi il tempo impiegato è un problema.
Elimina il dataset per le insert, leggi con la query quello che ti serve e poi inserisci in una TStringList tutte le insert di cui hai bisogno, in un unico script.
Una volta che hai preparato lo script dallo in pasto al server in un colpo solo, vedrai che i tempi saranno diversi e di molto.
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 22, 2014, 01:12:58 pm
ok per la query per leggere i dati (se non erro le query readonly sono anche più veloci).

quando devi fare un inserimento massivo non passare per il dataset se poi il tempo impiegato è un problema.
Elimina il dataset per le insert, leggi con la query quello che ti serve e poi inserisci in una TStringList tutte le insert di cui hai bisogno, in un unico script.
Una volta che hai preparato lo script dallo in pasto al server in un colpo solo, vedrai che i tempi saranno diversi e di molto.

grazie del consiglio. provero' e faro' sapere
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 22, 2014, 02:38:17 pm
Nomore, per dare in pasto al server lo script creato come faccio? Che suggerisci?

Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 22, 2014, 03:09:16 pm
Ho usato l'oggetto TZSQLProcessor e sembra funzionare alla grande. Grazie mille  ;)
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 22, 2014, 03:49:49 pm
Rettifico, queste sono le tempistiche per i 1260 record

15:47:32 --> 15:49:09
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 22, 2014, 07:21:17 pm
caspita non c'è differenza...
non capisco, è veramente strano.

Prendi lo stesso script e lancialo da flame robin, quanto ci mette?
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 23, 2014, 01:11:58 pm
Mi sono un po' informato, il problema è di ubuntu. Ora farò delle prove con altri OS per vedere se è vero e come muovermi. Grazie
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 24, 2014, 06:55:16 pm
leggi qua
http://www.firebirdsql.org/manual/gfix-sync.html (http://www.firebirdsql.org/manual/gfix-sync.html)

prova ad impostare la scrittura asincrona, il comando dovrebbe essere:
Codice: [Seleziona]
gfix -write async database_name

penso che così dovresti ottenere un significativo aumento delle prestazioni
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 25, 2014, 11:51:14 am
leggi qua
http://www.firebirdsql.org/manual/gfix-sync.html (http://www.firebirdsql.org/manual/gfix-sync.html)

prova ad impostare la scrittura asincrona, il comando dovrebbe essere:
Codice: [Seleziona]
gfix -write async database_name

penso che così dovresti ottenere un significativo aumento delle prestazioni

Provo e ti faccio sapere. Grazie mille :)
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 25, 2014, 12:56:33 pm
Nomore sei un angelo funziona alla grande  8)
Titolo: Re:Allineare tabelle
Inserito da: nomorelogic - Febbraio 25, 2014, 01:05:56 pm
grande :) che tempi ottieni ora?
Titolo: Re:Allineare tabelle
Inserito da: xinyiman - Febbraio 25, 2014, 03:00:34 pm
Dieci secondi per 1260 record. Prima ci metteva 2 min e mezzo. L'unica cosa è che ce rischio di errore se va via la corrente o qualsiasi altra cosa perchè la commit non ritorna errore.

Comunque va bene, così posso fare dei test e poi se servirà metterò il mio software su mint, debian o altro. Grazieeeeeeee