Pe server-ul unde este baza de date sursă:
CREATE DATABASE PseudoSincronizareSursa
GO
USE PseudoSincronizareSursa
GO
CREATE TABLE Produs
(
CodProdus INT PRIMARY KEY,
DenumireProdus VARCHAR(50) NOT NULL,
Stare ROWVERSION NOT NULL --ROWVERSION <=> TIMESTAMP
)
GO
CREATE UNIQUE INDEX idx_produs_stare
ON Produs (Stare)
GO
/*
--Ai posibilitatea sa se defineste un index care sa includa toate campurile
--care trebuiesc exportate din sursa in destinatie
CREATE INDEX idx_produs_stare
ON Produs (Stare,CodProdus,DenumireProdus)
*/
INSERT INTO Produs (CodProdus,DenumireProdus) VALUES (1,'Mere')
INSERT INTO Produs (CodProdus,DenumireProdus) VALUES (2,'Portocale')
INSERT INTO Produs (CodProdus,DenumireProdus) VALUES (3,'Lamai')
INSERT INTO Produs (CodProdus,DenumireProdus) VALUES (4,'Pere')
GO
Pe fiecare server unde există câte o bază de date destinaţie:
CREATE DATABASE PseudoSincronizareDestinatie
GO
USE PseudoSincronizareDestinatie
GO
CREATE TABLE Produs
(
CodProdus INT PRIMARY KEY,
DenumireProdus VARCHAR(50) NOT NULL,
Stare BINARY(8) NOT NULL
)
GO
EXEC sp_addlinkedserver
@server = 'LINK_SQLSERVER_SURSA',
@srvproduct = '',
@provider = 'SQLNCLI',
@datasrc = 'OOSQL\SQLEXPRESS',
@catalog = 'PseudoSincronizareSursa'
GO
--activezi optiunea RPC OUT pentru serverul "linked"
EXEC master.dbo.sp_serveroption
@server='LINK_SQLSERVER_SURSA',
@optname='rpc out',
@optvalue='true'
GO
EXEC sp_addlinkedsrvlogin
@rmtsrvname = 'LINK_SQLSERVER_SURSA',
@useself = 'TRUE',
@locallogin = 'oosql\bgdn'
GO
CREATE PROCEDURE spSincronizare
AS
DECLARE @tbl TABLE ( CodProdus INT, DenumireProdus VARCHAR(50), Stare BINARY(8) )
DECLARE @max ROWVERSION
SET @max = ISNULL( (SELECT MAX(Stare) FROM Produs) , 0x0 )
INSERT INTO @tbl (CodProdus, DenumireProdus, Stare)
SELECT CodProdus, DenumireProdus, Stare
FROM LINK_SQLSERVER_SURSA.PseudoSincronizareSursa.dbo.Produs
WHERE Stare > @max
UPDATE Produs
SET Produs.DenumireProdus = T.DenumireProdus, Produs.Stare = T.Stare
FROM @tbl AS T
WHERE Produs.CodProdus = T.CodProdus
INSERT INTO Produs (CodProdus, DenumireProdus, Stare)
SELECT CodProdus, DenumireProdus, Stare
FROM @tbl AS T
WHERE T.CodProdus NOT IN (SELECT CodProdus FROM Produs)
GO
În mod asemănător cu exemplul anterior, pentru sincronizare apelezi procedura stocată
EXEC spSincronizare
În continuare, poti adăuga şi modifica date în baza de date sursă:
INSERT INTO Produs (CodProdus,DenumireProdus) VALUES (5,'Soareci optici')
UPDATE Produs SET DenumireProdus = 'Ala bala portocala' WHERE CodProdus = 2
si sa realizezi sincronizarea din nou
EXEC spSincronizare
Observaţii:
[1] În tabela sursă se defineşte un câmp Stare de tip timestamp / rowversion. Valorile acestui câmp sunt coduri unice generate automat de server crescător (conform BOL). Avantajul acestui tip de date - în acest caz - vine din faptul că în momentul modificării unei înregistrări în baza de date sursă (bd PseudoSincronizareSursa) se modifică automat şi valoarea din câmpul timestamp / rowversion Stare, generându-se un nou cod pentru înregistrarea respectivă.
[2] Plecându-se de la valoarea maximă rowversion/timestamp din campul Stare a tabelei destinaţie Produs (bd PseudoSincronizareDestinatie) se pot filtra datele din tabela sursă Produs (bd PseudoSincronizareSursa). Daca în baza de date sursă se modifică/inserează 100 de înregistrari dintr-un total de 10.000 prin această filtrare, server-ul destinaţie primeşte de server-ul sursă doar 1% din înregistrări (adică 100 de înregistrări) spre deosebire de implementarea anterioară în care server-ul destinaţie primeşte de la serverul sursă toate înregistrarile: 100% (adică 10000). Lucru acesta se poate observa analizând planurile de execuţie.
[3] Soluţia se aplică doar pentru inserarea şi modificarea produsele, dar se poate adapta şi pentru cazul în care se doreşte ştergerea de produse.
[4] Parţial - doar pentru sincronizarea produselor noi inserate - soluţia poate fi aplicată daca există doar un câmp numeric IDENTITY care nu contine valori nule.