Wysyłka raportów dla kontrahentów

0

Hej,
Mam małą zagwozdkę. Potrzebuję wysłać dla klientów zestawienia dokumentów z okresu z datą płatności.
Samo zapytanie mam i działa jeśli przekaże ID kontrahenta.
Problem mam w tym, jak dla każdego ID kontrahenta osobno wywołać zapytanie.

Zapytanie w uproszczeniu wygląda mniej więcej tak:

Select [Nazwa_kontrahenta], Dokument, Termin, Limit 
from kontrahent
where knt_id=@ID

Myślałem nad zrobieniem tabelki z ID kontrahentów, ale jak później to wywołać, aby każdemu kontrahentowi wygenerować tylko zestawienie z jego dokumentami?
Chyba, że jest jakiś prostszy sposób na ogarnięcie tego?

1

Sprawdź pod Cursor https://docs.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-ver15

Na wujku G będziesz miał dużo przykładów jak użyć. Ale ostrzegam Cursor to zło ;) (@Panczo)

0

Czegoś nie rozumiem, SQL ma generowoać te zapytania i wysyłać raporty?

0
Select [Nazwa_kontrahenta], Dokument, Termin, Limit 
from kontrahent
where knt_id in (@ID1, @ID2 ... @IDN) 

choć w przypadku oracle ten in może mieć chyba tylko 1000 elementów.

Możesz też zrobić podzapytanie na warunek

knt_id in (select knt_id from ...) 

Oczywiście to da Ci listę wszystkich kontrahentów naraz ;), a co dalej to już ciężko powiedzieć bez konkretów

1
woolfik napisał(a):
> Select [Nazwa_kontrahenta], Dokument, Termin, Limit 
> from kontrahent
> where knt_id in (@ID1, @ID2 ... @IDN) 
> ```
> choć w przypadku oracle ten in może mieć chyba tylko 1000 elementów.

Ale to MSSQL a nie jakiś tam Oracle ;-)

A w MSSQL ograniczenie jest takie, że nikt nie wie jakie dokładnie i mnie to zawsze bawi :D
Dokumentacja mówi tak:
*"Explicitly including an extremely large number of values (**many thousands** of values separated by commas) within the parentheses, in an IN clause can consume resources and return errors 8623 or 8632. To work around this problem, store the items in the IN list in a table, and use a SELECT subquery within an IN clause."*
https://docs.microsoft.com/en-us/sql/t-sql/language-elements/in-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15#remarks

No po prostu bajka ;-)

Ale faktycznie mi się zdarzyło już wykonywać zapytania z `in` w którym jest *many thousands* elementów i problemów z tym nie miałem, zatem - może i tak :)
0
Panczo napisał(a):

Czegoś nie rozumiem, SQL ma generowoać te zapytania i wysyłać raporty?

Niby może, ale jeśli jest lepsza alternatywa, to nie zamykam się na sugestię :)

1

@Lilpri: Ogólnie mssql może wysłać, maila, możesz napisać clr'a lub cokolwiek innego jednak trzeba to zrobić "z głową". Podam Ci przykład z jednej z największych firm sektora finasowego w polsce.

Baza oracle -> Pakiet RAPORTY -> Procedura fGenRapMonth -> Funkcja w zasadzie generuje plik CSV, który jest odkładany w jakimś folderze i wpis do tabelki (nazwijmy ją SEND_RAPS) z nazwą pliku. W pierwszej wersji na tabeli był trigger, który przy użyciu UTL_MAIL wysyłał plik do klienta zaraz po zrobieniu insert. Niestety przy dużej ilości insertów potrzebny był czas na nawiązanie połączenia i wysłania maila więc robiły się opóźnienia spowodowane "wiszeniem" sesji. Przerobnione zostało to na schedulera, który uruchamia się cyklicznie na oddzielnej sesji, odczytuje tabelę, wysyła maila i oznacza wpis w tabeli jako wysłany. Działało to przez jakiś czas niestety nowe rynki finansowe to nowe wymagania jak np nowa (albo raczej druga) skrzynka do wysyłania maila więc UTL_MAIL został przerobiony na JAVE( klasa java zaimportowana do oracle). Niestety gdy doszły mechanizmy typu komunikacja REST, FTP, WEBAPI, itd. to scheduler został wyłączony i zastąpiony microservisem w javie, który odczytuje tabelę z wysyłką sprawdza gdzie co i jakim sposobem wysłać i tyle ;)

0

No można uzyć do tego SQLServer, z moich doświadczeń jednak wynika, że zrobienie tego z jego uzyciem, zawsze kończy się przepisaniem na inne rozwiazanie.
Z prostej przyczyny bez znajomosci tsql ciężko to przekazać ludziom odpowiedzialnym za wysyłkę, a zmiany i chęć rozbudowy zawsze się pojawia.

Sposobów jest sporo, poszukaj w sieci;
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b9f59a4b-710b-4907-8313-dea27f63e1a1/loop-through-query-results-and-send-dynamic-content-mail-from-db-mail?forum=transactsql

0

Mam napisany program (usługa windowsowa) który sprawdza co jakiś czas czy wysłać jakiś raport np. co 30s, jeżeli tak to wysyła potem for eachem z listy raportów. Jakbyś był zainteresowany mogę trochę zmodyfikować go pod Twoje potrzeby.

Ale tak jak wyżej wymienieni napisali, najlepiej jest zrobić to jakąś procedurą która:

  1. Wyciągnie ID kontrahenta gdzie trzeba wysłać raport.
  2. Whilem, for each, for, pętlą zrobi dla każdego raport, wyśle itp.

W samym SSMS jest funcja do wysyłania maili, raportów itp. jednak co program zewnętrzny to lepsza sprawa bo można jakoś tym zarządzać.

Coś jak tutaj:

https://stackoverflow.com/questions/889532/send-email-for-each-row-in-a-result-set

"The best way to accomplish this is to put your email sending logic in a user defined function.

Then you would simply call SELECT MyEmailFunc(emailaddress) FROM MyTable

It avoids loops and you can even use it in an update statement to show that the email was sent. For example:

UDPATE MyTable SET SENT = MyEmailFunc(emailaddress) WHERE sent = 0"

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