Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: While nie działa w procedurze?? MS SQL2000

HELP!
Wewnątrz proceury mam zawarty kawałek z while.
Chodzi o to, by dopóki istnieją rekordy spełniające jakiś tam warunek - robił jakiś update, i sprawdzał znów... (ponieważ update może sprawić, że pojawią się kolejne spełniające - stąd while).
@param jest parametrem przekazywanym do procedury. Kawałek od declare - jest w procedurze. I ... zonk. Nie zawsze działa. Czasem się biesi? Nie wiem, co się dzieje, nie mam narzędzia do podglądu, ale.. poniższy kawałek (bez pierwszych dwóch wierszy - umieszczony w procedurze - nie działa (w każdym razie tracę cierpliwość po 4 minutach). Odpalony z query analysera - działa.(1 s)
Wewnątrz procedury działał. Poprzednio pomogło usunięcie procedury i utworzenie jej na nowo - TYM SAMYM KODEM. Tym razem nie pomogło, poza tym, użytkownik nie ma takiej możliwości.
Siwieję. (with recompile nie pomogło też :()
HELP!

declare @param decimal(20,0)
set @param=100

declare @TableTmp table (id decimal(20,0))

insert into @TableTmp(id)
select --duży select z joinami na wielu tabelach

while (select count(*) from @TableTmp) >0
begin
update tab set pole='wartosc'
from tabela tab
where tab.id in(select id from @TableTmp)

delete from @TableTmp

insert into @TableTmp(id)
select --duży select z joinami na wielu tabelach jak pierwszy
end
Magdalena Łach

Magdalena Łach AX senior developer

Temat: While nie działa w procedurze?? MS SQL2000

Hej.

ja bym zrobiła tak:
1. kawałek: "select count(*) from @TableTmp" zamieniłabym na EXISTS
2. update tab set pole='wartosc'
from tabela tab
where tab.id in(select id from @TableTmp)
zamieniłabym na inner join... (mam uczulenie na in-y;)

dasz rade sprawdzic np. sp_who2 co sie dzieje na bazie?
jezeli cos raz dziala a innym razem nie, moze byc tak, ze np. tabela jest zalockowana... przez jakies dane cos sie kitwasi;)
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: While nie działa w procedurze?? MS SQL2000

W T-SQL zdaje się @@ROWCOUNT jest odpowiednikiem SQL%ROWCOUNT. No to wtedy można

update tab 
set pole = 'wartosc'
where id in (select --duży select z joinami na wielu tabelach);
while (@@rowcount > 0)
begin
update tab
set pole = 'wartosc'
where id in (select --duży select z joinami na wielu tabelach);
end;


Nie jestem zbyt biegły w strategii lockowania w sql serwerze, ale chyba w Twojej wersji może się zdarzyć, że czasem update'ujesz za wiele / za mało rekordów - jak ktoś podmieni zawartość "dużego selecta" pomiędzy zgarnięciem rekordów i update'm. No ale nie wiem co to za system, kto i jak go używa...Więc ciężko powiedzieć ;-) Tak czy siak tutaj update jest atomowy i ja bym mu bardziej ufał.Grzegorz G. edytował(a) ten post dnia 27.07.09 o godzinie 17:46
Adam O.

Adam O. Bazy danych etc

Temat: While nie działa w procedurze?? MS SQL2000

Ja bym połączył obydwie strategie;)

Czyli coś w stylu:

select NULL

while (@@ROWCOUNT > 0)
update tab
set pole = 'wartosc'
from tab
inner join (select costam) as tab2 on (tab2.ID = tab.ID)

Soją drogą update w while'u to masakrash i proszenie się o problemy, na pewno nie da się tego inaczej napisać? I czy to musi być sql 2k ?;)
Moje trzy grosze.
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: While nie działa w procedurze?? MS SQL2000

Dziękuję za rady, zaraz popoprawiam i zobaczę co z tego wyjdzie :)

Adam - przyznaję, while nie jest elegancki, ale nie znam ilości wykonań...
Zasadniczo problem polega na tym, że mam dwie tabele. Jedna połączona jest z samą sobą po id, id_nadrzedne, oraz z inną tabelą
t1.id->t1.id_nadrzedne
t1.id->t2.id_do_t1
w obydwu tabelach mam pole - powiedzmy "odpada".
Muszę poodznaczać te rekordy z t1 które nie mają "czystych" wierszy ani w t1 ani w t2.
Stąd nieznana ilość powtórzeń.
Obrazowo:

id id_nadrz
1 0
2 1
3 1
4 1
5 2
6 2
7 3
8 7
9 8
10 9

t2
id id_z_t1 odrzucony
1 1
2 1
3 4 tak

to...
muszę zrobić update na t1 i odznaczyć 10, 6, 5 i 4 - bo nie ma odpowiednika w t2(z czystym odrzuconym) ani nie ma powiązania do t1
następnie kolejny - 9 i 2 - bo JUŻ nie ma 10 ani 6 i 5, nie ma też odpowiednika w t2
następnie 8 - bo odpadła 9
7 - bo odpadła 8
3 - bo odpadła 7
ostatecznie zostaje mi 1.

Ok... przyjęto założenie, że nie może być więcej niż 20 powiązań t1 z t1.

id id_nadrz
1 0
2 1
3 2
...
19 18
20 19


czyli max 20 wykonań. Ale... czy to lepsze niż while?

Może macie lepszy pomysł?
Wdzięczna za sugestie pozdrawiam.

Edit:
Tabele są "usera".
Dane są tam wrzucane z serwera produkcyjnego, by nie obciążać, i "obrabiane" z boku. Nie ma na nich żadnych lock'ów robionych przez kogoś innego. Chyba, że sama siebie zblokuję. :[

Edit2:
Magia MS...
Procedura pobiera parametr @Sesja decimal(20,0).
Tenże parametr jest jednym z warunków w selectach.

Jako, że z poziomu query samo zapytanie działało, dopisałam w procedurze
declare @Sesja2 decimal(20,0)
set @Sesja2=@Sesja

i zmieniłam w selectach z @Sesja na @Sesja2...

Wiecie co?
Działa...

Dla ułatwienia dodam, że w zeszłym tygodniu procedura działała.
Ciekawe, kiedy teraz przestanie działać.

PS. Anyway, i tak się przesiadłam na rowcount'a. :) Dziękuję.
Mam nadzieję, że nie otworzę tego wątku za dwa-trzy dni...Edyta Ratajczyk edytował(a) ten post dnia 28.07.09 o godzinie 09:23
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: While nie działa w procedurze?? MS SQL2000

W gruncie rzeczy teraz to kwestia sprowadza się do pytania, czy masz jakieś funkcje rekurencyjne w Twojej bazie czy nie.
Jeżeli tak - to mogłoby to wyglądać mniej więcej w ten sposób:
update drzewko 
set do_wyrzucenia = 'tak';

update drzewko
set do_wyrzucenia = 'nie'
where id in (select id_z_drzewka from tabelka_z_flagami where do_wyrzucenia = 'nie');

update drzewko
set do_wyrzucenia = 'nie'
where id in (
select id
from drzewko
start with do_wyrzucenia = 'nie'
connect by prior id = id_taty
);


Jeżeli nie, to możesz to załatwić jednym updatem - aczkolwiek potrzebujesz 20 predykatów połączonych OR (czyli: uaktualnij, jeżeli istnieje nie do wyrzucenia dziecko OR istnieje nie do wyrzucenia dziecko dziecka OR istnieje nie do wyrzucenia dziecko dziecka dziecka OR ...). Ja bym się bał takie coś uruchomić...

I oczywiście nijak się to ma do Twojego pytania "czemu nie działa" - ja bym obstawił, że z "dużym selectem" jest coś nie tak i objawia się tylko w jakiejś egzotycznej konfiguracji "innej tabeli". Ale rzecz jasna nie mam zielonego pojęcia jak jest w rzeczywistości :-). Tym niemniej zaatakowałbym problem od drugiej strony - tak jak w przykładzie, zaznaczałbym kto zostaje, a nie kto leci.
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: While nie działa w procedurze?? MS SQL2000

To nie tak.
Mam kawałek skryptu.
Odpalony nie jako procedura - działa.
Ubieram go w procedurę.
Create procedure nazwa @Parametr decimal(20,0)
begin
wklejam
end

odpalam procedurę - i już nie działa.
Tudzież mieli się kilkusetkrotnie dłużej (az nie mam cierpliwości).
Odpalone jako sekwencja poleceń ~1s
Odpalone jako procedura - po 5 minutach tracę cierpliwość.
Tematu już nie zmienię. Nie o while koniec końców chodziło.
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: While nie działa w procedurze?? MS SQL2000

Może http://stackoverflow.com/questions/440944/sql-server-q...

Następna dyskusja:

Zapytanie SQL nie działa




Wyślij zaproszenie do