Blog JSystems - uwalniamy wiedzę!

Szukaj
Animacja czterech kroków integracji w n8n: odczyt z Oracle, mapowanie typów węzłem Code, zapis do PostgreSQL i weryfikacja zapytaniem SQL - realne zrzuty z działającego workflow
Cała integracja w czterech krokach na realnych zrzutach z n8n: odczyt z Oracle, mapowanie typów, zapis do bazy docelowej i weryfikacja. Niżej rozkładamy każdy krok na czynniki pierwsze
Animacja przepływu integracji: Oracle ERP jako źródło, n8n w środku (odczyt SQL, mapowanie typów, zapis), a jako cel PostgreSQL lub MS SQL Server
Ten sam wzorzec działa dla dowolnej pary baz: źródło czytasz jednym węzłem, cel zapisujesz drugim, a w środku mapujesz typy i kolumny

Z tego artykułu dowiesz się:

  • Dlaczego n8n bywa najszybszym sposobem na przeniesienie danych między bazami
  • Jak dodać do n8n obsługę bazy Oracle i połączyć się z nią bez instalowania klienta
  • Jak zbudować migrację Oracle do PostgreSQL krok po kroku: odczyt, mapowanie typów, zapis
  • Jak zrobić synchronizację cykliczną z harmonogramem i operacją upsert, żeby uniknąć duplikatów
  • Kiedy sięgnąć po n8n, a kiedy po dedykowane narzędzie migracyjne

Prawie każda firma z historią ma dwie bazy, które muszą się „widzieć". Stary system ERP siedzi na Oracle, a nowa aplikacja albo hurtownia raportowa stoi już na PostgreSQL - albo dowolna inna kombinacja baz, w tym Microsoft SQL Server, MySQL lub MariaDB, MongoDB czy Snowflake (n8n ma dla nich gotowe węzły). Dane trzeba przenieść raz przy starcie projektu, a potem regularnie dosynchronizowywać, żeby po obu stronach było to samo. Klasyczne odpowiedzi na ten problem to napisanie własnego skryptu (który potem ktoś musi utrzymywać) albo wdrożenie ciężkiego narzędzia ETL (drogiego i często przerośniętego dla prostej integracji). Pełną, klasyczną migrację całego schematu dedykowanym narzędziem opisaliśmy w osobnym przewodniku migracja Oracle do PostgreSQL - to inna metoda niż ta, którą pokażemy w tym artykule.

Jest trzecia droga: n8n. To narzędzie do automatyzacji typu low-code (mało kodu), w którym przepływ danych układasz z gotowych klocków zwanych węzłami. Ma natywne węzły do PostgreSQL, MySQL i Microsoft SQL Server, a Oracle dokładasz jednym kliknięciem. W tym artykule zbudujemy prawdziwą integrację Oracle do PostgreSQL i pokażemy ją na zrzutach z działającego workflow. Pokażemy też wariant z zapisem do MS SQL Server, bo ten sam wzorzec obsługuje dowolną bazę docelową. Termin ETL (Extract, Transform, Load, czyli pobierz, przekształć, załaduj) będzie się przewijał, ale całą tę robotę wyklikamy, zamiast ją programować.

1. Dlaczego n8n do integracji baz danych

Wartość n8n w tym zadaniu bierze się z trzech rzeczy. Po pierwsze, gotowe węzły baz danych: łączysz się przez formularz (host, port, użytkownik, hasło), a n8n zajmuje się sterownikiem i połączeniem. Po drugie, podgląd danych po każdym kroku: widzisz dokładnie, co wyszło z bazy źródłowej, co zrobiła transformacja i co wleciało do bazy docelowej. Po trzecie, wbudowany harmonogram, ponowienia i logi, więc synchronizacja cykliczna to kwestia jednego węzła, a nie osobnego zadania w systemie.

Poniżej efekt, do którego dojdziemy. To realny workflow uruchomiony w n8n: cztery węzły, wszystkie zielone, a nad połączeniami widać, ile elementów przepłynęło (jeden wynik z Oracle rozłożony na dwanaście wierszy zapisanych w PostgreSQL).

Workflow n8n po uruchomieniu: Start migracji, Oracle pobierz kontrahentów, Mapuj typy i kolumny, PostgreSQL zapisz - wszystkie węzły zielone, 12 items
Gotowa migracja w n8n po uruchomieniu: Start -> Oracle -> Mapuj typy i kolumny -> PostgreSQL. Nad połączeniami liczba przetworzonych elementów

2. Co budujemy - scenariusz

Weźmy typową sytuację. W bazie Oracle (stary ERP) mamy tabelę KONTRAHENCI z klientami firmy: identyfikator, nazwa, NIP, miasto, segment, data rejestracji, limit kredytowy i flaga aktywności. Chcemy przenieść tych kontrahentów do PostgreSQL, gdzie stoi nowa aplikacja i raportowanie. Tabela docelowa kontrahenci ma te same dane, ale w konwencji PostgreSQL: nazwy kolumn małymi literami, typ logiczny boolean zamiast liczbowej flagi, kolumna ze znacznikiem czasu ostatniej synchronizacji.

Ta pozorna drobnostka (wielkie kontra małe litery, NUMBER(1) kontra boolean, format daty) to sedno każdej integracji baz. Właśnie po to w środku przepływu stanie węzeł, który mapuje jedno na drugie. W naszym zbiorze jest dwunastu kontrahentów o łącznym limicie kredytowym 2 290 000 zł. Po migracji dokładnie te liczby powinny pojawić się po stronie PostgreSQL, co na koniec sprawdzimy.

3. Węzeł źródła: Oracle

PostgreSQL, MySQL i Microsoft SQL Server mają w n8n węzły od razu. Oracle dokładasz jako węzeł społecznościowy (community node), czyli rozszerzenie napisane przez społeczność. Wchodzisz w Ustawienia -> Community nodes, klikasz „Install", wpisujesz nazwę pakietu n8n-nodes-oracle-database i potwierdzasz. Po chwili w wyszukiwarce węzłów pojawia się „Oracle Database". Nowsze wydania n8n mają też natywny węzeł Oracle, ale wariant społecznościowy ma jedną wygodną cechę: łączy się w trybie thin, czyli czysto w JavaScripcie, bez instalowania klienta Oracle na serwerze.

Cała instalacja to kilka prostych kroków w panelu n8n:

Ekran Ustawienia Community nodes w n8n przed instalacja: pusta lista z komunikatem Supercharge your workflows with community nodes i przyciskiem Install a community node
Krok 1: Ustawienia -> Community nodes. Na początku lista jest pusta - klikasz pomarańczowy przycisk Install a community node
Okno Install community nodes w n8n: pole npm Package Name wypelnione wartoscia n8n-nodes-oracle-database, zaznaczony checkbox zgody, aktywny przycisk Install
Krok 2: w oknie instalacji wpisujesz nazwę pakietu n8n-nodes-oracle-database, zaznaczasz zgodę na instalację i klikasz Install
Ekran Community nodes w n8n po instalacji: na liscie pakiet n8n-nodes-oracle-database z opisem 1 node Oracle Database v0.0.1
Krok 3: po instalacji pakiet n8n-nodes-oracle-database pojawia się na liście (jeden węzeł: Oracle Database) i jest już dostępny w wyszukiwarce węzłów

Zakładamy przepływ: wyzwalacz „Start migracji"

Zanim dodamy Oracle na kanwę, tworzymy sam przepływ. Każdy workflow w n8n zaczyna się od wyzwalacza (trigger) - węzła, który go uruchamia. W nowym, pustym workflow n8n pokazuje pole Add first step i pyta „What triggers this workflow?". Wybierasz Trigger manually (uruchomienie ręczne, przyciskiem Execute), bo migrację chcemy odpalać na żądanie, i nazywasz ten pierwszy węzeł Start migracji. To on będzie punktem startowym całego przepływu.

Nowy pusty workflow w n8n: kanwa z polem Add first step, po prawej panel What triggers this workflow z opcja Trigger manually
Start przepływu: w nowym, pustym workflow wybierasz wyzwalacz Trigger manually (uruchamiany ręcznie przyciskiem) i nazywasz go Start migracji

Z gotowym wyzwalaczem Start migracji na kanwie dodajesz węzeł źródła: klikasz +, wpisujesz Oracle w wyszukiwarce węzłów i wybierasz Oracle Database (dostępny właśnie dzięki zainstalowanemu pakietowi społecznościowemu).

Wyszukiwarka wezlow w n8n po wpisaniu Oracle pokazuje wynik Oracle Database; na kanwie stoi wyzwalacz Start migracji
Z wyzwalaczem Start migracji na kanwie wpisujesz Oracle w wyszukiwarce węzłów i wybierasz Oracle Database - to nasze źródło danych

Zanim jednak węzeł cokolwiek pobierze, trzeba podłączyć do niego poświadczenie bazy. Po dodaniu węzła Oracle Database na kanwę otwierasz go, a na górze ustawień masz pole Credential. Ponieważ nie utworzyliśmy jeszcze żadnego poświadczenia Oracle, widnieje tu napis No credentials yet i przycisk Set up credential. Pole SQL Statement zostawiasz na razie puste (szara podpowiedź to tylko przykład) - zapytanie wpiszemy dopiero po podłączeniu bazy.

Wezel Oracle Database w n8n bez poswiadczenia: pole Credential z napisem No credentials yet i przyciskiem Set up credential, ponizej puste pole SQL Statement
Nowy węzeł Oracle Database nie ma jeszcze poświadczenia - w polu Credential widnieje No credentials yet i przycisk Set up credential. Pole SQL Statement niżej jest puste (szara podpowiedź to tylko przykład) - zapytanie wpiszemy po podłączeniu bazy

Po kliknięciu Set up credential otwiera się formularz nowego połączenia (Oracle Credentials). Wypełniasz w nim trzy pola: użytkownika, hasło i łańcuch połączenia w formacie host:port/nazwa_uslugi (u nas serwis FREEPDB1), a na dole włączasz przełącznik Use Thin mode.

Formularz poswiadczenia Oracle Credentials w n8n: pola User, Password, Conecction String w formacie host:port/serwis oraz wlaczony przelacznik Use Thin mode
Formularz poświadczenia: użytkownik, hasło i łańcuch połączenia w formacie host:port/nazwa_uslugi, plus włączony przełącznik Use Thin mode

Dopiero z podłączonym poświadczeniem wracasz do węzła i wypełniasz jego jedyne pole - SQL Statement. Wpisujemy zwykły SELECT. Datę od razu formatujemy funkcją TO_CHAR na łańcuch YYYY-MM-DD, żeby przeszła przez sterownik w czystej, przewidywalnej postaci.

-- Zapytanie w węźle Oracle (źródło)
SELECT ID_KONTRAHENTA, NAZWA, NIP, MIASTO, SEGMENT,
       TO_CHAR(DATA_REJESTRACJI, 'YYYY-MM-DD') AS DATA_REJESTRACJI,
       LIMIT_KREDYTOWY, AKTYWNY
FROM KONTRAHENCI
ORDER BY ID_KONTRAHENTA

Po wpisaniu zapytania zostaje uruchomienie. Klikasz Execute step u góry węzła, a n8n łączy się z Oracle, wykonuje SELECT i w panelu OUTPUT po prawej pokazuje pobrane wiersze.

Edytor wezla Oracle Database w n8n przed uruchomieniem: panel INPUT bez danych, posrodku zapytanie SQL, po prawej OUTPUT bez danych i przycisk Execute step
Edytor węzła przed uruchomieniem: po lewej wejście, w środku zapytanie, po prawej pusty jeszcze panel wyniku. Zapytanie odpalasz przyciskiem Execute step u góry - dopiero wtedy w panelu OUTPUT pojawiają się dane
Węzeł Oracle w n8n: pole SQL Statement z zapytaniem SELECT, po prawej wynik z polami metadata i rows
Ten sam węzeł już po uruchomieniu - w panelu OUTPUT po prawej pojawił się wynik zapytania. Zwróć uwagę, że przyszedł jako jeden element z tablicą rows w środku

Tu pojawia się pierwsza rzecz, którą trzeba wiedzieć o tym węźle: całe zapytanie zwraca jeden element, a wszystkie wiersze siedzą w polu rows tego elementu. To nie problem, tylko cecha, którą obsłużymy w następnym kroku. Widać to zresztą na zrzucie: po prawej stronie jest metadata (opis kolumn) i rows z listą kontrahentów.

4. Transformacja: mapowanie typów i kolumn

Między źródłem a celem wstawiamy węzeł Code (kawałek JavaScriptu). Dodajemy go tak samo jak każdy inny węzeł: klikamy + (na kanwie albo na łączniku między dwoma węzłami), wpisujemy w wyszukiwarce Code i wybieramy z listy pozycję Code z podpisem „Run custom JavaScript or Python code". Jeśli klikniesz plus dokładnie na połączeniu Oracle z celem, n8n sam wepnie nowy węzeł w środek przepływu.

Panel dodawania węzła w n8n z wpisaną frazą Code; na liście podświetlona pozycja Code (Run custom JavaScript or Python code), w tle kanwa z węzłami Start migracji, Oracle: pobierz kontrahentów i Mapuj typy i kolumny
Dodanie węzła Code: wpisujemy „Code" w wyszukiwarce węzłów i wybieramy pierwszą pozycję z listy. Trafi między węzeł źródłowy a docelowy

Po dodaniu węzeł robi dwie rzeczy naraz. Najpierw rozkłada pojedynczy element z Oracle na dwanaście osobnych wierszy (iterujemy po rows). Potem mapuje każdy wiersz na konwencję PostgreSQL: nazwy kolumn z wielkich liter na małe, liczbową flagę AKTYWNY (1 lub 0) na wartość logiczną true lub false. Datę zostawiamy jako łańcuch YYYY-MM-DD, bo PostgreSQL sam rzutuje ją na typ date.

// Węzeł Code: rozłóż wynik Oracle (pole rows) i zmapuj typy
// Oracle (WIELKIE litery, DATE, 1/0) -> PostgreSQL (małe litery, date, boolean)
const wynik = [];
for (const item of $input.all()) {
  for (const r of item.json.rows) {
    wynik.push({ json: {
      id_kontrahenta:   r.ID_KONTRAHENTA,
      nazwa:            r.NAZWA,
      nip:              r.NIP,
      miasto:           r.MIASTO,
      segment:          r.SEGMENT,
      data_rejestracji: r.DATA_REJESTRACJI,
      limit_kredytowy:  r.LIMIT_KREDYTOWY,
      aktywny:          r.AKTYWNY === 1
    }});
  }
}
return wynik;

Efekt widać najlepiej właśnie w tym węźle. Po lewej stronie mamy surowe wejście z Oracle, w środku kod, a po prawej czystą tabelę dwunastu wierszy gotowych do zapisu: małe nazwy kolumn, kolumna aktywny jako true lub false, poprawne daty i liczby. To jest ta „litera T" z ETL, tylko wyklikana i widoczna gołym okiem.

Węzeł Code w n8n: po lewej surowe dane z Oracle, w środku kod mapujący, po prawej tabela 12 zmapowanych kontrahentów z kolumnami małymi literami i wartościami boolean
Transformacja w akcji: surowy wynik Oracle po lewej, kod pośrodku, a po prawej dwanaście gotowych wierszy z poprawnymi typami i nazwami kolumn

Wskazówka: gdy mapowanie jest proste (tylko zmiana nazw kolumn), zamiast węzła Code możesz użyć wizualnego węzła Edit Fields i przeciągać pola myszką. Węzeł Code wybieramy, gdy potrzebujemy logiki, takiej jak konwersja 1/0 na wartość logiczną albo rozłożenie zagnieżdżonego wyniku na osobne wiersze.

5. Węzeł celu: PostgreSQL (zapis)

Ostatni klocek to natywny węzeł PostgreSQL. Dokładasz go tak samo jak poprzednie: klikasz + na końcu przepływu, wpisujesz w wyszukiwarce węzłów Postgres i wybierasz z listy węzeł Postgres.

Panel dodawania węzła w n8n z wpisaną frazą Postgres; na liście podświetlony natywny węzeł Postgres, w tle kanwa przepływu
Dodanie węzła docelowego: w wyszukiwarce węzłów wpisujemy „Postgres" i wybieramy natywny węzeł Postgres

Najpierw podłączasz poświadczenie. W polu Credential wybierasz Create New Credential i wypełniasz zwykłe dane połączenia: host, bazę, użytkownika, hasło i port. Po zapisaniu n8n od razu testuje połączenie - zielony komunikat „Connection tested successfully" potwierdza, że baza odpowiada.

Formularz poświadczenia PostgreSQL w n8n: pola Host, Database, User, Password, komunikat Connection tested successfully
Poświadczenie PostgreSQL: host, baza, użytkownik, hasło i port. n8n testuje połączenie od razu po zapisaniu

Z podłączonym poświadczeniem konfigurujesz sam zapis. Operację ustawiamy na Insert, wskazujemy schemat public, tabelę kontrahenci i listę kolumn do zapisu. n8n dopasowuje pola wejściowe do kolumn po nazwie, dlatego wcześniejsze mapowanie na małe litery było ważne: nazwy z węzła Code muszą zgadzać się z nazwami kolumn w PostgreSQL. Po kliknięciu Execute step w panelu OUTPUT po prawej pojawia się dwanaście faktycznie zapisanych wierszy.

A jeśli nazwy się nie zgadzają? n8n dopasowuje pola po nazwie, więc rozjazd kończy się na jeden z dwóch sposobów. Kolumna, dla której nie ma pasującego pola (klasyczny przypadek: węzeł Code zwraca NAZWA wielkimi literami, a kolumna w PostgreSQL to nazwa), dostaje wartość NULL - dane z niej po cichu przepadają. A jeśli taka pominięta kolumna ma ograniczenie NOT NULL (na przykład klucz główny id_kontrahenta), cały zapis kończy się błędem null value in column "id_kontrahenta" violates not-null constraint, a węzeł zatrzymuje przepływ na czerwono. Dlatego mapowanie w węźle Code na dokładnie te same, małe nazwy kolumn jest tak ważne - inaczej albo tracisz dane bez ostrzeżenia, albo dostajesz błąd zapisu. To samo dotyczy węzła Microsoft SQL i każdej innej bazy docelowej.

Węzeł PostgreSQL w n8n: operacja Insert, schemat public, tabela kontrahenci, lista kolumn; po prawej 12 zapisanych wierszy
Węzeł PostgreSQL w trybie Insert: schemat, tabela i kolumny. Po prawej dwanaście wierszy faktycznie zapisanych do bazy

Na koniec sprawdzamy bazę docelową bezpośrednio zapytaniem SQL - w węźle PostgreSQL przełączamy operację na Execute Query i zliczamy wiersze. W PostgreSQL wylądowało dwanaście wierszy o łącznym limicie kredytowym 2 290 000 zł (dokładnie tyle, ile w Oracle) i jedenastu aktywnych kontrahentach, bo jeden miał flagę wyłączoną. Migracja przeszła w całości i z poprawnym mapowaniem typów.

Węzeł PostgreSQL w n8n w trybie Execute Query z zapytaniem zliczającym; wynik: liczba_wierszy 12, suma_limitow 2290000, aktywni 11
Weryfikacja po stronie PostgreSQL: zapytanie zliczające zwraca 12 wierszy, sumę limitów 2 290 000 i 11 aktywnych kontrahentów - dokładnie tyle, ile w źródłowym Oracle

Wariant: ten sam zapis do Microsoft SQL Server

Celem nie musi być PostgreSQL. Ta sama układanka działa dla Microsoft SQL Server - zmienia się tylko węzeł zapisu, a reszta przepływu (źródło Oracle i węzeł Code z mapowaniem) zostaje bez zmian. Węzeł MS SQL dodajesz identycznie: klikasz +, w wyszukiwarce wpisujesz Microsoft SQL i wybierasz węzeł z listy.

Panel dodawania węzła w n8n z wpisaną frazą Microsoft SQL; na liście węzeł Microsoft SQL, w tle kanwa przepływu do MS SQL Server
Dodanie węzła docelowego Microsoft SQL: w wyszukiwarce wpisujemy „Microsoft SQL" i wybieramy natywny węzeł

Poświadczenie wygląda niemal identycznie jak dla PostgreSQL, z drobną różnicą nazewnictwa: pole nazywa się Server zamiast Host, a domyślny port to 1433. Reszta to ta sama baza, użytkownik i hasło. Tu również n8n potwierdza połączenie od razu po zapisaniu.

Formularz poświadczenia Microsoft SQL w n8n: pola Server, Database, User, Password, Port 1433, komunikat Connection tested successfully
Poświadczenie Microsoft SQL: pole Server, baza, użytkownik, hasło i port 1433. Połączenie przetestowane pomyślnie

Konfiguracja zapisu też jest bliźniacza: operacja Insert, tabela kontrahenci i ta sama lista kolumn. Węzeł MS SQL nie pyta osobno o schemat (domyślnie dbo). Po uruchomieniu w panelu OUTPUT znów pojawia się dwanaście zapisanych wierszy.

Węzeł Microsoft SQL w n8n: operacja Insert, tabela kontrahenci, lista kolumn; po prawej 12 zapisanych wierszy
Węzeł Microsoft SQL w trybie Insert: tabela i kolumny jak w PostgreSQL. Po prawej dwanaście wierszy zapisanych do MS SQL Server

Weryfikacja jest analogiczna - Execute Query z zapytaniem zliczającym. Jedyna różnica składniowa to CAST(aktywny AS INT) zamiast CASE WHEN, bo w MS SQL typ logiczny to BIT. Wynik ten sam: 12 wierszy, 2 290 000 zł limitów i 11 aktywnych kontrahentów.

Węzeł Microsoft SQL w n8n w trybie Execute Query z zapytaniem zliczającym; wynik: liczba_wierszy 12, suma_limitow 2290000, aktywni 11
Weryfikacja po stronie Microsoft SQL Server: 12 wierszy, suma limitów 2 290 000 i 11 aktywnych - identycznie jak w PostgreSQL

6. Synchronizacja cykliczna: harmonogram i upsert

Jednorazowa migracja to dopiero połowa historii. W praktyce dane w Oracle się zmieniają, więc PostgreSQL (lub inną bazę docelową) trzeba regularnie dosynchronizowywać. Zmieniamy w tym celu dwie rzeczy. Pierwszą jest wyzwalacz: zamiast ręcznego startu wstawiamy węzeł Schedule Trigger, który sam uruchamia przepływ w zadanym rytmie, na przykład co godzinę.

Kolejność jest tu ważna, bo najpierw pozbywamy się starego wyzwalacza. Klikasz na kanwie węzeł Start migracji i naciskasz Delete (albo klikasz go prawym przyciskiem myszy i wybierasz Delete). Na kanwie zostaje sam potok - Oracle: pobierz kontrahentów, Mapuj typy i kolumny, PostgreSQL: zapisz - bez żadnego węzła startowego. Ponieważ każdy przepływ musi mieć wyzwalacz, n8n od razu pokazuje ten sam panel, co przy zakładaniu pustego workflow: What triggers this workflow? (gdyby nie pojawił się sam, otwierasz go przyciskiem + / Add first step na początku potoku). Tym razem w jego wyszukiwarce wpisujesz Schedule i wybierasz Schedule Trigger (na liście wyzwalaczy to pozycja „On a schedule" - uruchamianie według harmonogramu). Nowy wyzwalacz podłącza się przed węzłem Oracle i przejmuje rolę dawnego Start migracji.

Panel What triggers this workflow w n8n po wpisaniu Schedule pokazuje wynik Schedule Trigger; na kanwie potok Oracle, Mapuj typy i kolumny, PostgreSQL bez wyzwalacza
Po usunięciu ręcznego Start migracji n8n znów pyta o wyzwalacz (panel „What triggers this workflow?"). W jego wyszukiwarce wpisujesz „Schedule" i wybierasz Schedule Trigger. Na kanwie stoi już gotowy potok (Oracle, mapowanie, PostgreSQL) bez węzła startowego, do którego dokładasz harmonogram

Po wybraniu węzeł otwiera się na zakładce Parameters - i to tu ustawiasz rytm uruchomień. W sekcji Trigger Rules masz listę Trigger Interval, w której wybierasz jednostkę: Seconds, Minutes, Hours, Days, Weeks, Months albo Custom (Cron). W zależności od wyboru pojawiają się dodatkowe pola. Dla naszego „co godzinę" wybieramy Hours, ustawiamy Hours Between Triggers na 1 (co ile godzin, zakres 1-23), a w Trigger at Minute wpisujemy 0 - dzięki temu przepływ rusza na początku każdej godziny (o pełnej minucie). Gdybyś potrzebował innego rytmu, zmieniasz jednostkę: Days dodaje pola „o której godzinie" i „w której minucie", Weeks pozwala wskazać dni tygodnia, a Custom (Cron) udostępnia pole na wyrażenie cron, na przykład 0 6 * * 1-5 (w dni robocze o 6:00). Przyciskiem Add Rule możesz dołożyć kolejne reguły, jeśli chcesz kilka różnych harmonogramów w jednym wyzwalaczu (na przykład częściej w godzinach pracy, rzadziej nocą).

Węzeł Schedule Trigger w n8n, zakładka Parameters: Trigger Interval ustawiony na Hours, Hours Between Triggers 1, Trigger at Minute 0
Wyzwalacz Schedule Trigger: przepływ rusza sam według harmonogramu, tu co godzinę. Nie potrzebujesz osobnego zadania cron w systemie

Drugą zmianą jest sposób zapisu. Przy powtarzalnym uruchamianiu zwykły insert próbowałby dodać te same wiersze po raz drugi i wywalił się na kluczu głównym. Zamiast tego używamy upsert (od update plus insert): jeśli kontrahent o danym identyfikatorze jeszcze nie istnieje, wiersz zostaje wstawiony; jeśli już jest, zostaje zaktualizowany. W PostgreSQL robi to konstrukcja INSERT ... ON CONFLICT ... DO UPDATE. W węźle PostgreSQL przełączamy operację na Execute Query i wpisujemy zapytanie z tą konstrukcją.

-- Węzeł PostgreSQL w trybie Execute Query: upsert (wstaw lub zaktualizuj)
INSERT INTO kontrahenci
  (id_kontrahenta, nazwa, nip, miasto, segment, data_rejestracji, limit_kredytowy, aktywny)
VALUES
  ({{$json.id_kontrahenta}}, '{{$json.nazwa}}', '{{$json.nip}}', '{{$json.miasto}}',
   '{{$json.segment}}', '{{$json.data_rejestracji}}', {{$json.limit_kredytowy}}, {{$json.aktywny}})
ON CONFLICT (id_kontrahenta) DO UPDATE SET
  nazwa = EXCLUDED.nazwa, nip = EXCLUDED.nip, miasto = EXCLUDED.miasto,
  segment = EXCLUDED.segment, data_rejestracji = EXCLUDED.data_rejestracji,
  limit_kredytowy = EXCLUDED.limit_kredytowy, aktywny = EXCLUDED.aktywny,
  zsynchronizowano = now();

Jeśli celem jest MS SQL Server, upsert robimy inaczej, bo ta baza nie zna ON CONFLICT. Odpowiednikiem jest polecenie MERGE, które w jednym kroku dopasowuje wiersze po kluczu i albo je aktualizuje (gałąź WHEN MATCHED), albo wstawia (gałąź WHEN NOT MATCHED). To samo zadanie, inna składnia:

-- Węzeł Microsoft SQL w trybie Execute Query: upsert (MERGE)
MERGE kontrahenci AS cel
USING (SELECT
    {{$json.id_kontrahenta}} AS id_kontrahenta, '{{$json.nazwa}}' AS nazwa, '{{$json.nip}}' AS nip,
    '{{$json.miasto}}' AS miasto, '{{$json.segment}}' AS segment,
    '{{$json.data_rejestracji}}' AS data_rejestracji, {{$json.limit_kredytowy}} AS limit_kredytowy,
    {{$json.aktywny}} AS aktywny
  ) AS zrodlo
ON cel.id_kontrahenta = zrodlo.id_kontrahenta
WHEN MATCHED THEN UPDATE SET
    nazwa = zrodlo.nazwa, nip = zrodlo.nip, miasto = zrodlo.miasto,
    segment = zrodlo.segment, data_rejestracji = zrodlo.data_rejestracji,
    limit_kredytowy = zrodlo.limit_kredytowy, aktywny = zrodlo.aktywny,
    zsynchronizowano = GETDATE()
WHEN NOT MATCHED THEN INSERT
    (id_kontrahenta, nazwa, nip, miasto, segment, data_rejestracji, limit_kredytowy, aktywny)
  VALUES
    (zrodlo.id_kontrahenta, zrodlo.nazwa, zrodlo.nip, zrodlo.miasto,
     zrodlo.segment, zrodlo.data_rejestracji, zrodlo.limit_kredytowy, zrodlo.aktywny);

Dwie różnice warte zapamiętania: w MS SQL polecenie MERGE musi kończyć się średnikiem (inaczej dostaniesz błąd składni), a bieżący czas bierzemy z funkcji GETDATE() zamiast now(). Reszta działa tak samo - jeden identyfikator dopasowuje wiersz, brak dopasowania oznacza wstawienie nowego.

Warto też ograniczyć, ile danych pobieramy ze źródła przy każdym przebiegu. Jeśli tabela źródłowa ma kolumnę ze znacznikiem modyfikacji (na przykład DATA_MODYFIKACJI albo updated_at), dokładamy do zapytania źródłowego warunek WHERE DATA_MODYFIKACJI >= SYSDATE - 1 i bierzemy tylko rekordy zmienione w ostatniej dobie. Takiej kolumny jednak nie zawsze mamy - wtedy zostają inne podejścia:

  • Pełna synchronizacja co przebieg - przepisujemy całą tabelę za każdym razem. Dzięki upsertowi jest to bezpieczne (żadnych duplikatów), tylko cięższe przy dużych zbiorach.
  • Znacznik postępu (watermark) - dla tabel, które tylko rosną, pobieramy rekordy o identyfikatorze lub dacie utworzenia większych niż ostatnio przeniesione, a najwyższą przeniesioną wartość zapamiętujemy między uruchomieniami (choćby w osobnej tabeli stanu).
  • Dodanie kolumny w źródle - jeśli mamy wpływ na bazę źródłową, dokładamy kolumnę z datą modyfikacji (albo trigger, który ją odświeża) i wracamy do prostego warunku po dacie.

Niezależnie od wybranej strategii sam upsert gwarantuje, że powtórne przebiegi aktualizują istniejące wiersze zamiast tworzyć duplikaty.

Węzeł PostgreSQL w n8n w trybie Execute Query z zapytaniem INSERT ON CONFLICT DO UPDATE (upsert)
Ten sam węzeł PostgreSQL, ale w trybie Execute Query z upsertem. Powtórne uruchomienia aktualizują wiersze zamiast je duplikować

Całość drugiego przepływu wygląda niemal tak samo jak migracja, tylko z innym wyzwalaczem i innym trybem zapisu. Uruchomiliśmy go i po stronie PostgreSQL dalej było dwanaście wierszy (żadnych duplikatów), za to ze świeżym znacznikiem synchronizacji, co potwierdza, że upsert zadziałał.

Workflow synchronizacji cyklicznej w n8n: Co godzinę, Oracle zmienieni kontrahenci, Mapuj typy i kolumny, PostgreSQL upsert - wszystkie zielone
Synchronizacja cykliczna: wyzwalacz harmonogramu zastępuje ręczny start, a końcowy węzeł robi upsert zamiast prostego insertu

7. To samo dla MySQL, MS SQL i innych baz

Najważniejsze w tym podejściu jest to, że wzorzec się nie zmienia. „Źródło -> mapowanie -> cel" wygląda identycznie niezależnie od tego, jakie bazy łączysz. Chcesz przenieść dane z Microsoft SQL Server do PostgreSQL? Podmieniasz pierwszy węzeł na natywny Microsoft SQL. Synchronizujesz MySQL z Oracle? Zmieniasz węzły na końcach, a środek (mapowanie typów) zostaje. Dzięki temu jeden raz nauczony schemat obsługuje dowolną parę baz, także w tę i z powrotem.

Jeśli pary baz nie musisz łączyć przez zewnętrzne narzędzie, tylko chcesz odpytywać jedną bazę z drugiej, to osobny mechanizm; opisaliśmy go w artykule o linkach bazodanowych w PostgreSQL. n8n przydaje się tam, gdzie dane trzeba realnie przenieść, przekształcić po drodze albo połączyć z innym systemem czy API.

8. Kiedy n8n, a kiedy dedykowane narzędzie

n8n nie zastępuje wszystkiego. Przy jednorazowym przeniesieniu bardzo dużej bazy z pełnym, wiernym odwzorowaniem schematu, indeksów i ograniczeń lepiej sięgnąć po dedykowane narzędzie migracyjne. Rozłożyliśmy taki proces na czynniki pierwsze w osobnym tekście: migracja Oracle do PostgreSQL, kompletny przewodnik. n8n błyszczy tam, gdzie liczy się szybkość budowy, cykliczna synchronizacja i czytelny podgląd danych.

Porównanie: ręczny skrypt (elastyczny, ale kosztowny w utrzymaniu), ciężkie narzędzie ETL (drogie), n8n (low-code, gotowe węzły, podgląd danych, harmonogram wbudowany)
Ręczny skrypt daje pełną kontrolę kosztem utrzymania, ciężki ETL bywa przerostem formy dla prostych integracji, a n8n łączy szybkość budowy z podglądem i harmonogramem

Do produkcyjnego uruchomienia takiego przepływu przyda się jeszcze jedno: własna, stabilna instancja n8n. Jak ją postawić, opisaliśmy w artykule jak postawić n8n na własnym serwerze. Wtedy integracje działają u Ciebie, a dane bazy nie opuszczają Twojej infrastruktury.

Cała ta układanka sprowadza się do jednego: integracja baz danych nie musi oznaczać pisania i utrzymywania ETL-a. Trzy węzły, jedno mapowanie i harmonogram wystarczą, żeby Oracle i PostgreSQL trzymały te same dane, a Ty widzisz każdy krok jak na dłoni zamiast zgadywać, co poszło nie tak w skrypcie.

Szkolenie n8n + AI: sztuczna inteligencja w automatyzacji firmy

Integracje z bazami i API, agenci AI, automatyzacja procesów w firmie i budowa własnych workflow na żywo podczas praktycznego szkolenia. Prowadzi Sebastian Koziatek, a szkolenie ma termin gwarantowany, więc odbędzie się niezależnie od liczby zgłoszeń.

n8n + AI: automatyzacja firmy

Najczęściej zadawane pytania

Czy n8n potrafi łączyć się z bazą Oracle?
Tak. PostgreSQL, MySQL i Microsoft SQL Server mają w n8n gotowe, natywne węzły. Dla Oracle instalujesz węzeł społecznościowy (na przykład n8n-nodes-oracle-database) przez Ustawienia i węzły społecznościowe, a nowsze wersje n8n mają też natywny węzeł Oracle. Węzeł społecznościowy łączy się w trybie thin, czyli nie wymaga instalowania klienta Oracle.
Czym różni się migracja jednorazowa od synchronizacji cyklicznej w n8n?
Migracja jednorazowa uruchamiana jest ręcznie (wyzwalacz Manual) i przenosi wszystkie rekordy jeden raz operacją insert. Synchronizacja cykliczna używa wyzwalacza harmonogramu (Schedule), pobiera tylko rekordy zmienione od ostatniego przebiegu i zapisuje je operacją upsert (w PostgreSQL INSERT ... ON CONFLICT, w MS SQL Server polecenie MERGE), więc powtarzalne uruchomienia nie tworzą duplikatów, tylko aktualizują istniejące wiersze.
Jak w n8n zmapować typy danych między Oracle a PostgreSQL?
Między węzłem źródła a węzłem celu wstawiasz węzeł Code (JavaScript) lub Edit Fields. Tam zamieniasz nazwy kolumn (Oracle zwraca je wielkimi literami) na nazwy z PostgreSQL, a także konwertujesz typy: liczbowe flagi 1/0 na wartości logiczne true/false, a daty formatujesz jako łańcuch YYYY-MM-DD, który PostgreSQL rzutuje na typ date.
Czy n8n nadaje się do dużych migracji baz danych?
n8n świetnie sprawdza się w integracjach i synchronizacjach o rozsądnej skali oraz tam, gdzie liczy się szybkość budowy i czytelny podgląd danych. Przy jednorazowym przeniesieniu bardzo dużej bazy z pełnym mapowaniem schematu warto rozważyć dedykowane narzędzia migracyjne. Oba podejścia dobrze się uzupełniają.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...