Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Witam.
Mam dziwny problem.

Jest w bazie na Oracle 10i tabela, w której jedno z pól nazywa się 'STA_I' i jest typu varchar2(1), ponadto jest pole 'ID' które jest kluczem głównym.
Potrzebuję zrobić update nie więcej niż 5-ciu wierszy, w których STA_I = 'N'. Update ma zmienić STA_I na 'P'. Załóżmy, że nie interesuje mnie kolejność wierszy - po prostu nie więcej niż 5 na raz i już.

W MSSQL robię to tak:

update TABELA
set STA_I = 'P'
where ID in ( select top (5) ID
from TABELA
where STA_I = 'N' )


W Oracle nie ma top(), więc wymyśliłem to tak:

update TABELA
set STA_I = 'P'
where ID in ( select ID
from ( select ID
from TABELA
where STA_I = 'N' )
where rownum < 5 )


I teraz obydwa zapytania śmigają pięknie z poziomu odpowiednich developerów (MSSQL i PL/SQL).
Zapytanie MSSQL działa też dobrze z poziomu aplikacji C#/.NET.
Natomiast zapytanie Oraclowe wiesza mi aplikację C#/.NET !!!!
Jako data providera używam wbudowanej w .NET framework klasy System.Data.OracleClient. Zwykłe selecty chodzą OK. Powyższy update wiesza aplikację :( bez rzucania jakiegokolwiek wyjątku!

I zarys aplikacji (pomijam sprawdzanie i obsługę błędów):


OracleConnection conn = new OracleConnection(connString);
conn.Open();

string sql = <zapytanie_oraclowe_jak_powyżej>
OracleCommand cmd = new OracleCommand(sql);

cmd.Connection = conn;
cmd.CommandType = CommandType.Text;

int i = (int)cmd.ExecuteNonQuery();
Write("Returns: " + i.ToString());

cmd.Dispose();

conn.Close();
conn.Dispose();


Czyli nic specjalnego.
WTF?????????Piotr G. edytował(a) ten post dnia 17.03.10 o godzinie 21:13
Michał K.

Michał K. Specjalista Oracle
PL/SQL.

Temat: Oracle: update z limitem wiesza aplikację????

rownum jest specyficzna pseudokolumna oracle, moze klient nie rozumie czegos takiego?

konto usunięte

Temat: Oracle: update z limitem wiesza aplikację????

a niby czego miał by nie rozumieć? wyniku w postaci cyfry?
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Może... Ale nigdzie nie znalazłem informacji o takim ograniczeniu... No i sprawdziłem: klient rzuca wyjątkiem jeśli natrafi na nieistniejącą nazwę kolumny (zmieniłem 'rownum' na 'dupa')...
Co więcej, tabela obecnie ma raptem kilkaset wierszy, więc nawet jeśli rownum byłby stały (i mniejszy od 5-ciu), to najwyżej zrobiłby się update wszystkich wierszy spełniających warunek, co trwałoby max dwie chwile :)
A to wisi bez końca - cierpliwości starczyło mi na 30 minut, potem dałem aplikacji po łbie.

Temat: Oracle: update z limitem wiesza aplikację????

Na co czeka? Może inna sesja update'uje te same wiersze i nie zrobila commit ?:)
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Nie wiem, na co czeka :(
Nie mam tego oracla u siebie: jest na drugim końcu Polski u klienta.
Co więcej, nie jestem w stanie ani podejrzeć jego logów czy czegotam trzeba, ani tym bardziej restartować czy coś.
Ponadto - jak pisałem: z poziomu PL/SQL Developera tenże sam update śmiga w każdą stronę jak trzeba - także wtedy, kiedy jednocześnie aplikacja wisi.

Ale, ale... Coś mi się chyba kiedyś obiło o uszy, że System.Data.OracleClient wymaga opakowania update'ów w transakcję? To prawda? Wiecie coś może?
Kurczę, nie mogę tego znaleźć...
Łukasz Schabek

Łukasz Schabek Architekt Rozwiązań

Temat: Oracle: update z limitem wiesza aplikację????

Nie mam doświadczenia w .NET, lecz miałem podobny problem z Javą. Jeśli to krytyczna funkcjonalność, możesz zastosować obejście; wrzuć instrukcję UPDATE w procedurę i wywołuj ją z odpowiednimi parametrami.
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Nie moge zrobić procedury :(
Jeśli bym mógł zrobić, to dawno byłoby po kłopocie :)
Mogę tylko czytać z i pisać do niektórych pól w niektórych tabelach (a tak naprawdę w widokach). Oracle jest nie nasz, nie my nim administrujemy, maszyna jest nie nasza i aplikacja na tym Oracle'u też jest nie nasza :(Piotr G. edytował(a) ten post dnia 17.03.10 o godzinie 20:52
Łukasz Schabek

Łukasz Schabek Architekt Rozwiązań

Temat: Oracle: update z limitem wiesza aplikację????

omg, warunki bojowe...

może tak?

UPDATE tabela a
SET sta_i = 'P'
WHERE EXISTS (
SELECT 1
FROM (
SELECT ID, rownum as foo
FROM tabela
WHERE sta_i = 'N'
) b
WHERE b.ID = a.ID
AND b.foo < 5
)


nic innego nie przychodzi mi do głowyŁukasz Schabek edytował(a) ten post dnia 17.03.10 o godzinie 21:03
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

To niestety nie zadziała - dlatego, że rownum liczony jest przez oracla zawsze dla wszystkich wierszy, które przez niego "przelatują" w ramach selecta, a nie tylko dla tych, które załapią się na where.
Dlatego właśnie na forach oraclowych polecają nie łączyć rownum z żadnymi innymi warunkami - jeśli trzeba łączyć, to robić to w zagnieżdżonych selectach, i rownum dawać najbardziej "na zewnątrz".

No i pamiętajmy, że problemem nie jest zapytanie jako takie - bo to, które ja podałem, działa dobrze z designera.
Problemem jest to, dlaczego ono wiesza aplikację?
Marcin P.

Marcin P. Software Engineer /
PL/SQL Developer

Temat: Oracle: update z limitem wiesza aplikację????

Skoro nie masz uprawnień na procedurę może dałoby się załatwić to w bloku PL/SQL z instrukcją commit na końcu, ewentualnie z jakąś obsługą wyjątku, jeśli masz taką możliwość.
Coś w rodzaju:

BEGIN
--Twoja instrukcja update
COMMIT;
EXCEPTION
--spróbować przechwycić wyjątek i zobaczyć co się ewentualnie dzieje
END;

Temat: Oracle: update z limitem wiesza aplikację????

A jak wpiszesz:

update TABELA set STA_I = 'P' where ID in ( id1, id2 )

gdzie id1 , id2 to konkretne wartości id
to działa poprawnie?

Mam wrażenie, że jest LOCK na tabeli z innej transakcji i czeka na zwolnienie lub COMMIT/ROLLBACK.

Nie pamiętam jak jest C# - masz ustawiony autocommit?
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Marcin P.:
Skoro nie masz uprawnień na procedurę może dałoby się załatwić to w bloku PL/SQL z instrukcją commit na końcu, ewentualnie z jakąś obsługą wyjątku, jeśli masz taką możliwość.
Coś w rodzaju:

BEGIN
--Twoja instrukcja update
COMMIT;
EXCEPTION
--spróbować przechwycić wyjątek i zobaczyć co się ewentualnie dzieje
END;
Ciekawe - spróbuję.
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Piotr Wolański:
A jak wpiszesz:

update TABELA set STA_I = 'P' where ID in ( id1, id2 )

gdzie id1 , id2 to konkretne wartości id
to działa poprawnie?

Mam wrażenie, że jest LOCK na tabeli z innej transakcji i czeka na zwolnienie lub COMMIT/ROLLBACK.

Nie pamiętam jak jest C# - masz ustawiony autocommit?

Piotrek, na tą chwilę to na szczęście baza testowa i nic więcej na niej nie działa - raz ją napchali danymi, wyłaczyli napychaczkę i czekają na sygnał ode mnie, że już umiem to czytać.
Ale na 100% żaden inny proces nie trzyma żadnych rekordów ani transakcji.
Co więcej, tak jak pisałem na początku: dokładnie i literalnie ten sam update puszczony zarówno z poziomu PL/SQL Developera (na serwerze poprzez remote desktop), jak i z Oracle'owego klienta command line'owego (na moim laptoku 500km od serwera) działa dobrze i nigdy nic nie wiesza. Natomiast z C# zawsze wiesza - i oczywiście nic nie update'uje w tabeli.
A z tym autocommitem to nie wiem :( Nie widzę go we własnościach ani połaczenia, ani komendy :(

Generalnie wygląda to na jakąś specyfikę providera System.Data.OracleClient - ale właśnie zależy mi na tym, żeby poznać formalną przyczynę, a nie ją obchodzić.

konto usunięte

Temat: Oracle: update z limitem wiesza aplikację????

to kwestia commita, oracle nie wiesza sie tylko czeka na zatwierdzenie

Temat: Oracle: update z limitem wiesza aplikację????

No i pamiętajmy, że problemem nie jest zapytanie jako takie - bo to, które ja podałem, działa dobrze z designera.
No to mamy drugą sesję ;)
A jak w designerze dasz rollback to aplikacja rusza? :)
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Spokojnie, taki zielony to nie jestem :)
No nie mamy drugiej sesji: pamiętajmy, że samo zapytanie wykonuje się ułamek sekundy (zmieniam tylko 5 wierszy z kilkuset).
Aplikacja się wiesza zawsze - czy designer jest odpalony, czy nie.
Co więcej, aplikacja nigdy się nie odwiesza.
Designer natomiast nigdy się nie wiesza - nawet, jak właśnie wisi aplikacja.

Temat: Oracle: update z limitem wiesza aplikację????

W Oracle nie ma top(), więc wymyśliłem to tak:

OracleConnection conn = new OracleConnection(connString);
conn.Open();

string sql = <zapytanie_oraclowe_jak_powyżej>
OracleCommand cmd = new OracleCommand(sql);

cmd.Connection = conn;
cmd.CommandType = CommandType.Text;

int i = (int)cmd.ExecuteNonQuery();
Write("Returns: " + i.ToString());

cmd.Dispose();

conn.Close();
conn.Dispose();
BTW: sugerowałbym raczej opakowywanie obiektów ADO w usingi. Jeśli wyleci Ci wyjątek gdzieś po drodze, to nie zwolnisz niczego. conn.Dispose to to samo co conn.Close, nie trzeba wołać 2 razy.Jacek Tomaka edytował(a) ten post dnia 18.03.10 o godzinie 17:55
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Robert Kubalski:
to kwestia commita, oracle nie wiesza sie tylko czeka na zatwierdzenie

No tak podejrzewam, zresztą to już było sugerowane.
Tyle, że nie bardzo mam jak ten commit zrobić.
W MSSQL-u w jednym ciągu mogę zapisać kilka poleceń, rozdzielając je średnikiem ';'. Czyli umieszczenie commita na końcu nie jest problemem (abstrahując od tego, że w MSSQL-u nie jest on w ogóle potrzebny - update działa bez niego).
Natomiast Oracle, kiedy zapodam mu taki ciąg poprzez klienta z .NET Frameworka pokazuje mi fucka wrzeszcząc, że użyłem niedozwolonego znaku. Jest jakiś inny separator poleceń w Oracle'u niż średnik????
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Oracle: update z limitem wiesza aplikację????

Nie no, Panowie. Jestem zielony jak trawa na wiosnę.

Niniejszym składam samokrytykę :)

Rzeczywiście to designer trzymał tabelę (albo jej wiersze).
A konkretniej trzymały niezatwierdzone commitem testowe update'y, które robiłem na designerze wcześniej. Zmęczenie robi swoje :(

Jacek, Piotrek - mieliście rację.
Przy najbliższej okazji macie u mnie piwo.
Dla mnie to nauczka, żeby sprawdzać kilka razy zamiast upierać się, że skoro raz sprawdziłem to na 100% wiem.



Wyślij zaproszenie do