[MSSQL] Stworzenie triggera

0

Witam społeczność,
Proszę bardzo pilnie o pomoc w napisaniu triggera, który po dodaniu rekordu, skopiuje ten rekord do innych baz, zarówno w tej samej instancji, jak i w innych instancjach, ale te instancje są na tym samym serwerze. Pomoże ktoś?

PS.: Oczywiście mowa tu o tej samej tabeli w różnych bazach.

0

W czym dokładnie masz problem? Mamy napisać ten trigger za ciebie?

1

Prosisz sie o problemy :)

0

Problem mam, bo nie wiem od czego zacząć. Nigdy nie tworzyłem triggerów. To raz, a dwa, w ramach jednej instancji, to jeszcze sobie poradzę. Ale pomiędzy instancjami, to już średnio. Jakaś podpowiedź?

0

coś w ten deseń.

CREATE TRIGGER T_TableA_I
on TableA
after insert
as
    set nocount on

    insert into TableB (ColumnA,ColumnB,/* lista kolumn */)
    select a.ColumnA,a.ColumnB, /* lista kolumn z table a */
    from
        TableA a
            inner join
        inserted i
            on
                a.PKColumn1 = i.PKColumn1 and
                a.PKColumn2 = i.PKColumn2 /* Primary Key columns z table A */

jeśli masz inne instancje na tym samym serwerze czy w ogóle w LANie to najlepiej stwórz sobie Linked Server. Szukaj w necie dokładnie pod tym hasłem. To jest dosłownie kilka kliknięć w SSMS

1

Ale pomiędzy instancjami, to już średnio. Jakaś podpowiedź?

To jest dokładnie tak samo jak pomiędzy bazami, z tą różnicą że musisz utworzyć Linked Server, możesz w SSMS na drzewie Server Objects->Linked Servers kliknąć prawy przycisk myszy i wybrać opcje Add Linked Server

Lub przy pomocy t-sql, zakładając że serwer nazywa się serwer i ma dwie instancje i1 i i2 a trigger uruchamiasz na instancji i1 to

  1. Tworzysz linked server na instancji i1:
USE [master]
GO
EXEC master.dbo.sp_addlinkedserver @server = N'serwer\i2', @srvproduct=N'SQL Server'
GO
--tutaj logowanie za pomocą autoryzacji SQL użytkownikiem user i hasłem: haslo
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'serwer\i2', @locallogin = NULL , @useself = N'False', @rmtuser = N'user', @rmtpassword = N'haslo'
GO
/*ewentualne możliwości, logowanie przy pomocy aktualnie zalogowanego użytkownika:
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'serwer\i2', @locallogin = NULL , @useself = N'True'
GO
bez kontekstu:
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'serwer\i2', @locallogin = NULL , @useself = N'False'
GO
*/

i testujesz czy działa, np. zapytanie:

select * from [serwer\i2],baza.dbo.tabela

zwróć uwagę jak odwołujesz się do tabeli: nazwaserwer.nazwabazy.schemat,obiekt

No i też walisz triggera:

CREATE TRIGGER T_TableA_I
ON TableA
after INSERT
AS
    SET nocount ON
 
    INSERT INTO [serwer\i2].baza.dbo.tabela (ColumnA,ColumnB,/* lista kolumn */)
    SELECT a.ColumnA,a.ColumnB, /* lista kolumn z table a */
    FROM
               inserted i
go

Od siebie dodam, że to jest kombinacja alpejska, jak napiszesz triggera który rozrzuca dane po innych instancjach, to możesz natrafić na problemy, pamiętaj, że zapytania sql są wykonywane synchronicznie, pomyśl o tym co się stanie jak trigger ci się gdzieś wywali na komunikacji i zwróci błąd. To są rzeczy, które musisz przemyśleć na początku, aby calosci nie przepisywać.
Po zadanym pytaniu domyślam się że nie za bardzo ogarniasz samego SQL-a, ale przemyśl sobie co robisz, abys nie ugrząsł na problemie, jak użytkownicy zaczna zgłaszać że nie da się nic zapisać do bazy....

Ja w takim przypadku szedłbym w Service Brokera....

0

SQL-a jako takiego ogarniam. Niestety triggerów nigdy nie pisałem. Ja nie będę rzucał tymi danymi Bóg jeden wie ile. Chodzi o przepisywanie nowych rekordów z jednej bazy, do X baz. Przy czym, operacje tylko na jednej tabeli, z której system praktycznie tylko czyta (baza towarów). Rozszerzając zagadnienie. Jeden system, który zapisuje do bazy towary, kopiuje je do pozostałych, a pozostałe systemy tylko odczytują. Z resztą użytkownicy, nie mają praw zapisu do tej tabeli.

0

Wszystkim dzięki wielkie za pomoc. Trigger działa. Ale tylko jak dodaję rekord z poziomu SSMS. Kiedy próbuję dodać rekord z poziomu aplikacji (PC-Market), otrzymuję komunikat błędu jak poniżej:

[08004] [Microsoft][ODBC SQL Server Driver][SQL Server]Obiekt główny serwera „BAZA_1” nie jest w stanie uzyskać dostępu do bazy danych „BAZA_2” przy bieżącym kontekście zabezpieczeń.

Obydwie bazy są w tej samej instancji. Jakaś podpowiedź, gdzie szukać rozwiązania?

0

Zabezpieczenia, użytkownik który dodaje rekord nie ma dostępu do baza_2

0

Hmmm. Ale użytkownik w samej aplikacji, czy bazodanowy? Bo aplikację podłączałem do bazy przy pomocy użytkownika sa.

0

Bzaodanowy, jeżeli nic nie kombinowałeś to trigger uruchamia się w kontekście użytkownika dodającego rekordy

0

Czyli sa. Hmmmm. No to dziwne w takim razie, bo jest błąd sterownika ODBC.

0

Sprawdź dokładnie czy to faktycznie sa się łączy

0

@Panczo: Faktycznie. Połączenie jest nieco inaczej skonstruowane. W ramach jednej instancji sprawa rozwiązana.

Problem teraz pojawił się przy wywołaniu Triggera pomiędzy instancjami. Aplikacja pokazuje mi komunikat o treści:

Zapytania heterogeniczne wymagają ustawienia dla połączenia opcji ANSI_NULLS i ANSI_WARNINGS. Gwarantuje to spójność semantyki zapytań. Włącz te opcje, a następnie ponownie wykonaj zapytanie.

No i teraz jestem w małej kropce, bo nie za bardzo wiem gdzie tych ustawień szukać. Sprawdzałem w połączeniu ODBC w systemie operacyjnym. I jest ok. Nigdzie nie widzę tych opcji. Albo może inaczej. W miejscach, w których je znalazłem, to włączyłem.

0

ansi nulls trzymane jest na poziomie obiektu (upraszczając) więc musisz to zrobić w DDL-u:

SET ANSI_NULLS ON
GO
ALTER TRIGGER …


---twój insert

0

No tak właśnie robię. Tylko ten komunikat pojawia mi się przy INSERT do jednego z Linked Server.
A zastanawia mnie jeszcze jedno. Są ustawione obydwa parametry ANSI_NULLS i ANSI_WARNINGS. Ale kiedy próbuję modyfikować trigger, to w kodzie nie ma parametry ANSI_WARNINGS.

0

To go dodaj...

SET ANSI_NULLS ON
GO
SET ANSI_WARNINGS ON
GO
ALTER TRIGGER …
 

A w odbc powinny być tutaj, chyba, że aplikacja sama je wyłącza:
screenshot-20180813170203.png

Opcja use ANSI nulls...

Albo uruchom profilera i zobacz w zdarzeniu audit log co ustawia aplikacja kliencka.

0

życie samo chce Cię nauczyć innych wzorców programowanie, np system messaningowy jaki proponuje @Panczo.
Widzę udzielasz się w Delphi gdzie baza jest jedynym królem, ale na tym nie kończy sie informatyka

1 użytkowników online, w tym zalogowanych: 0, gości: 1