SQL problem z INSERT INTO w pętli

0

Witam wszystkich,

Mam taki kod który działa ok. Chodzi mi o dopisanie rekordu w tabeli tab z wartością ostatniego rekordu z tabeli tab1:

DECLARE @wynik INT = (SELECT TOP 1 col FROM db1.tab1 ORDER BY col DESC)
INSERT INTO db2.tab (col1,col2,col3,col4) VALUES (0, @wynik, 0, 0);

Wszystko działa dobrze, tylko teraz chcę uruchomić ten skrypt w pętli, który będzie się w zależności od warunków powtarzał (albo nie).
Oczywiście będzie błąd przy ponownym deklarowaniu @wynik.

Chciałem w jakiś sposób zastąpić w VALUES @wynik bezpośrednio zapytaniem SELECT... z pierwszej linii.
Czy można to jakoś zrobić?

Dziękuję z góry.

0

Zapytanie będzie bardziej czytelne, jeśli użyjesz zmiennej. Zmienną zadeklaruj raz przed pętlą, a potem w pętli ustawiaj jej wartość instrukcją SET.

1

Jezus, Maria i wszyscy święci ...
Czy w trakcie działania tej pętli dane w tab1 będą się zmieniały, że chcesz to dla każdej iteracji pobierać? Bo na moje oko to z db1.tab1 wyciągasz rekordy, które chcesz i walisz to w ten sposób:

insert into db2.tab(col1,col2,col3,col4)
(select 0, col, 0, 0 from db1.tab1 where ...) 

lub jak się upierasz na pętlę:

for rec in (select col from db1.tab1  where...) loop
  insert into db2.tab(col1,col2,col3,col4) values (0, rec.col, 0,0);
end loop;

choć ja na tym przykładzie nie widzę uzasadnienia dla pętli ... ja nie do końca ogarniam co chcesz zrobić ale jak opiszesz to jaśniej to pomogę konkretniej.

0

@ŁF: Dzięki, tak właśnie zrobiłem, na samym początku kodu dałem:
DECLARE @wynik INT

a później przed INSERT INTO...VALUES

SET @wynik =....

Jednak wychodzi "błąd SQL (137) Must declare the scalar variable @wynik".

0

@woolfik: Nie upieram się na pętlę, tak jak napisałem, TO zapytanie jest w pętli.
Jednak, rozwiązanie z INSERT INTO ... SELECT rozwiązałoby prawdopodobnie mój problem, gdybym umiał napisać warunek WHERE (czego nie umiem).
Warunkiem jest to, aby col było odczytane z ostatniego rekordu db1.tab1

0

Mylisz tabele (moim zdaniem) ... więc postaram się nieco jaśniej:
Napisałeś, że chcesz takiego inserta walnąć w pętli i chodzi o ten warunek pętli. Pobierasz 1 rekord (select top 1 col from db1.tab1 ORDER BY col DESC) jako stałą i niezmienną wartość i to możesz sobie zrobić tak jak zasugerował @ŁF wpisując przed pętlą do zmiennej i potem tylko podstawiając zmienną w insercie. ALE pojawia się pytanie skoro pobierasz tylko 1 rekord najnowszy z db1.tab1 to co chcesz robić w pętli? Dlaczego ten insert do db2.tab ma się wykonać "n" razy, a nie tylko 1 raz? W związku z powyższym zapytałem czy w trakcie działania tej pętli (np 100 mln iteracji, które mogą potrwać jakiś czas) dane w tabeli db1.tab1 mogą się zmienić. Jeśli tak to wtedy musisz sprawdzać wartość tego selecta wewnątrz pętli. Kluczowe jednak pozostaje pytanie jakie są warunki dotyczące "n" wpisów do tabeli db2.tab.

Jaśniej nie potrafię opisać czego nie kumam w Twoim problemie.

0

@woolfik: W pętli dodają się nowe rekordy do db1.tab1. I nie ma to związku z moim problemem. Przy spełnieniu pewnych warunków nowo dopisanego rekordu, chcę dodać nowy rekord w zupełnie innej tabeli db2.tab, wstawiając w jedno z pól (col2) wartość z najnowszego rekordu db1.tab1 (col). Próbowałem tak zrobić jak zasugerował @ŁF (opis powyżej) ale wyskakuje mi błąd. Zapewne coś robię źle. Dlatego, szukam alternatywy i spodobało mi się rozwiązanie INSERT INTO..SELECT ale nie umiem złożyć składni warunku WHERE żeby był brany pod uwagę najnowszy rekord w db1.tab1.

0

No to jeszcze prostsza sytuacja.

Robisz jakąś pętlę (nie wiem po czym ale robisz) więc coś takiego

for rec in (...) loop
  insert into db1.tab1 ... returning col into @zmienna;
  insert into db2.tab (col1, col2, ... coln) values (0, 0, ..., @zmienna, ...coln);
end loop;

dodając rekord w pętli do db1.tab1 pobierasz sobie col z tegoż inserta (bo po order by col desc) wnioskuję, że ten dodany aktualnie rekord jest tym najnowszym, poprzez returning zwracasz to do zmiennej i walisz inserta do db2.tab ze zmienną.

0

@woolfik: Dziękuję za pomoc. Niestety to rozwiązanie jest tym samym co mój wyjściowy kod, u Ciebie @zmienna u mnie nazywa się @wynik.
Wszystko się sprowadza do prostej rzeczy która stanowi problem jaką jest deklaracja tej zmiennej. Ponieważ kod działa w pętli i bardzo często dopisuje się inkrementalnie (ciężko mi to jaśniej wytłumaczyć, ale nie o to w tym chodzi), dopisałem deklarację tej zmiennej na początku kodu (poza pętlą, bo w niej deklarowałaby się w kółko co generowałoby błąd). Ponieważ też mi się wygenerował błąd jak to wcześniej opisałem, zacząłem sprawdzać i okazało się, że myślałem, że dopisałem na początku kodu, ale przez to że kod się dopisuje inkrementalnie to nie był to bezwzględny początek kodu (i też generował się błąd).
Problem mój więc sprowadzam do zagadnienia bardzo już uproszczonego, tak aby całkowicie uniknąć deklarację zmiennej:
Jak użyć poprawnie składni SQL w wyrażeniu INSERT INTO....SELECT....WHERE w ostatnim jego członie po WHERE, aby warunkiem spełnionym był brana pod uwagę wartość col z najnowszego rekordu db1.tab1.

2

where t1.col = (select max(col) from t2) jeśli chodzi Ci o to, czego używałeś na początku wątku. Składnia może być ciut inna w zalezności od implementacji sql serwera, którego używasz. Generalnie chodzi o podzapytanie.

0

@ŁF: Dzięki serdeczne, właśnie o to mi chodziło.
Pozdrawiam gorąco!

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