Pobranie nr wiersza z bazy Oracle

0

Czy ktoś spotkał się może z taką rzeczą? Chodzi o to, że piszę plugin w Javie do Eclipsa, który będzie operował na tabelach z bazy danych Oracle. Przykładowo posiadam listę rozwijaną JComboBox, w której znajdują się nazwy tabel pobranych z bazy. Po wybraniu jakiejkolwiek wyświetla mi się ona na panelu jako JTable z pobranymi danymi. Tu jest wszystko w porządku. Teraz chciałbym zrobić coś takiego, że po zaznaczeniu jakiejś komórki na JTabel, zwracam nr kolumny i nr wiersza. W Javie nie ma problemu :) tylko teraz pytanie jak wykonać coś takiego zapytaniem SQL :) dla update danej komórki, bo jeśli chodzi o nr kolumny ogarnąłem coś takiego

SELECT COLUMN_ID FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'FIRMA' AND COLUMN_ID = 3

Pobierając indeks z tabeli w Javie podaję go tu w zapytaniu. Teraz brakuję mi jeszcze nr wiersza, żeby edytować zaznaczoną komórkę nie tylko w tabeli, ale także w bazie danych. Nie bawię się w żadne id, bo musiałbym zaznaczać komórki tylko z id, żeby bez problemu to robić.

Czyli podsumowując, zaznaczam daną komórkę, pobiera mi indeks wiersza i kolumny. Przekazuję je do zapytania, które aktualizuję mi daną komórkę. UPDATE nazwa_tabeli SET zaznaczone pole w danej kolumnie WHERE nr_kolumny = indeks_kolumny_java and nr_wiersza = indeks_wiersza_javy.

Szukam i szukam i nie mogę się doszukać, jak to rozwiązać, problemem jest z nr wiersza...
Ma ktoś jakiś pomysł ? :) Myślę, że napisałem jasno.

0

To co chcesz zrobić jest bez sensu bo, o ile nie sortujesz danych w trakcie zapytania, kolejność rekordów jest niezdefiniowana. Możesz teoretycznie wykonać 10 selectów z bazy i za każdym razem uzyskać inną kolejność rekordów bo optymalizator kosztowy zdecyduje żeby dane pobierać raz w taki raz w inny sposób. Jakakolwiek zmiana w bazie a nawet w obciążeniu serwera i ilości dostępnej pamięci może wpłynąć na faktyczną realizację zapytania (np. czy będzie full table read czy za pomocą indeksów, albo jakiego algorytmu joinowania tabel użyć) i tym samym na inną kolejność rekordów wynikowych.

Więc nawet gdybyś teoretycznie mógł coś takiego wykonać to nie działałoby to tak jak byś chciał.

Niemniej nie rozumiem dlaczego nie użyjesz zwyczajnie ID. Przecież to nie problem z tego twojego JTable po zaznaczeniu komórki wybrać sobie ID z pierwszej komórki w tym samym wieszu. Pobierasz to ID i voila.

0

Nie do konca prawda @Shalom bo oracle ma cos takiego jak rowid. Natomiast bezsensowne jest to co chcesz zrobić bo jak sam piszesz UPDATE nazwa_tabeli SET zaznaczone pole w danej kolumnie WHERE nr_kolumny = indeks_kolumny_java po set musisz podac nazwe kolumny

0

@abrakadaber ale rowid jest poprawne dla danego zapytania a nie jest w zaden sposób globalne! Tzn rowid wskazuje na numer wiersza ale tylko w chwili wykonywania zapytania (więc możesz go użyć w podzapytaniu np. do limitowania liczby rekordów). Jak wykonasz zapytanie drugi raz to inny wiersz może mieć dane rowid.

0

Rownum jest dla wyniku zapytania a rowid jest unikalny dla tabeli albo calej bazy - nie pamietam i jednoznacznie identyfikuje rekord z zastrzezeniem, ze po usunieciu rekordu to rowid jest do ponownego użycia. Jednak nie zaistnieje sytuacja aby ten sam rekord zwrócił rozne rowid

0

tylko, że rowid zwraca coś takiego ... oracle.sql.ROWID@1f657068 , więc to raczej nic mi nie da :) za pomocą podanego przeze mnie zapytania normalnie mogę zwrócić nr kolumny, niestety z wierszem nie bardzo. A chciałem coś takiego, żeby po prostu usuwać dany wiersz naciskając na jakąkolwiek komórkę w wierszu, a nie specjalnie na specjalne pole w kolumnach np. id_firma, bo ktoś może tego nie wiedzieć..

0

Nie rozumiem dlaczego się uparłeś na nieużywanie ID ?Możesz przecież usunąć kolumnę z JTable a w modelu i tak będziesz miał dostęp do tej wartości.
Możesz użyć getSelectedRow potem getValueAt podajesz numer wiersza i kolumny i problem z głowy..

pozdrawiam

0

@Shalom za każdym razem używając

SELECT * FROM nazwa_tabeli

wyświetla mi się cała zawartość tabeli w tej samej kolejności, w jakiej wstawiłem pojedyncze rekordy używając insertów.

Słuchajcie mnie. Mam tabelę JTable widoczną na ss.
3fa3e5e258.png
Teraz chodzi o to, że podświetlony jest cały wiersz i bardziej zaznaczona komórka. W tym wypadku naciskając usuń, chcę usunąć ten wiersz, ale po pobraniu zaznaczonej obecnie wartości nie dojdę, które rekord ma być usunięty, bo w tej kolumnie może być kilka takich nazw. Jeśli chciałbym to robić na id nie ma problemu, tylko musiałbym zaznaczać tylko pola w pierwszej kolumnie, a chciałem to zrobić bez takiej potrzeby. Moim problemem jest stworzenie zapytania takiego, które zrobi mi UPDATE zaznaczonej komórki po pobraniu jej nr wiersza i nr kolumny.

Kombinuję na tej zasadzie

UPDATE nazwa_tabeli SET zaznaczone_pole_kolumny = nowa_nazwa_pola WHERE ((SELECT COLUMN_ID FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'nazwa_tabeli' AND COLUMN_ID = indeks_kolumny_JTable+1) = 1)

SELECT zwraca mi nr kolumny na podstawie zaznaczonego pola w JTable. Potrzebny drugi select, który zwróci mi nr wiersza, a tu jest ten problem :). Uważam, że nie jest to głupie do zwykłego obsługiwania prostych tabel (dodawanie/usuwanie/edytowanie tabel, dodawanie/usuwanie/ wierszy/kolumn itp...)

Jeśli nadal piszę coś niezrozumiale, to przepraszam, ale staram się jak mogę :)).

A jak już tu jestem, to żeby nie śmiecić i nie tworzyć nowych wątków, czy istnieje możliwość tworzenia pustej tabeli bez żadnych kolumn?

0
miki10194 napisał(a):

tylko, że rowid zwraca coś takiego ... oracle.sql.ROWID@1f657068 , więc to raczej nic mi nie da :)

no popatrz a u mnie jest coś takiego
user image

miki10194 napisał(a):

@Shalom za każdym razem używając

SELECT * FROM nazwa_tabeli

wyświetla mi się cała zawartość tabeli w tej samej kolejności, w jakiej wstawiłem pojedyncze rekordy używając insertów.

Ale Oracle nie gwarantuje, że tak będzie zawsze!! Jedyną gwarancją na powtarzalną kolejność jest wymuszenie sortowania przez dodanie ORDER BY do zapytania.

Teraz chodzi o to, że podświetlony jest cały wiersz i bardziej zaznaczona komórka. W tym wypadku naciskając usuń, chcę usunąć ten wiersz, ale po pobraniu zaznaczonej obecnie wartości nie dojdę, które rekord ma być usunięty, bo w tej kolumnie może być kilka takich nazw. Jeśli chciałbym to robić na id nie ma problemu, tylko musiałbym zaznaczać tylko pola w pierwszej kolumnie, a chciałem to zrobić bez takiej potrzeby. Moim problemem jest stworzenie zapytania takiego, które zrobi mi UPDATE zaznaczonej komórki po pobraniu jej nr wiersza i nr kolumny.

TO TAK NIE DZIAŁA. Nie wierzę, że nie da się pobrać wartości pierwszego (przyjmuję, że jest to pole klucz) pola z JTable, nawet jeśli zaznaczone jest inna. BTW JTable pewnie skądś pobiera dane - zaznaczanie wiersza w JTable nie aktualizuje "aktualnego" wiersza w tym czymś? Bo mam takie wrażenie, że podchodzisz do tego od tyłka strony.

A jak już tu jestem, to żeby nie śmiecić i nie tworzyć nowych wątków, czy istnieje możliwość tworzenia pustej tabeli bez żadnych kolumn?

nie - tabela MUSI mieć przynajmniej jedną tabelę

0
Jeśli chciałbym to robić na id nie ma problemu, tylko musiałbym zaznaczać tylko pola w pierwszej kolumnie, a chciałem to zrobić bez takiej potrzeby

Nie! Zaznaczasz cały wiersz a następnie używasz metody:
getSelectedRow która zwraca Ci inta z zaznaczonym wierszem.

Wiedząc, że id masz w kolumnie 0, za pomocą metody:

getValueAt(row-twój podświetlony wiersz,column-tutaj wstawiasz zero bo id masz na 0)<chyba w takiej kolejności ale nie pamiętam) dostajesz id wiersza których chcesz usunąć z tabeli albo co tam chcesz z nim zrobić.

Pozdrawiam

0
miki10194 napisał(a):

@Shalom za każdym razem używając

SELECT * FROM nazwa_tabeli

wyświetla mi się cała zawartość tabeli w tej samej kolejności, w jakiej wstawiłem pojedyncze rekordy używając insertów.

Ale tak nie musi się stać.

Jeśli chciałbym to robić na id nie ma problemu, tylko musiałbym zaznaczać tylko pola w pierwszej kolumnie, a chciałem to zrobić bez takiej potrzeby.

Ale po co zaznaczać jakieś pola? Można zaznaczać cały wiersz. ID można (a nawet należy) w ogóle nie wyświetlać.

Moim problemem jest stworzenie zapytania takiego, które zrobi mi UPDATE zaznaczonej komórki po pobraniu jej nr wiersza i nr kolumny.

Twoim problemem jest to, że próbujesz naprawić silnik przez rurę wydechową zamiast zrobić tak, jak robi się to normalnie.

Uważam, że nie jest to głupie do zwykłego obsługiwania prostych tabel (dodawanie/usuwanie/edytowanie tabel, dodawanie/usuwanie/ wierszy/kolumn itp...)

Głupie nie, po prostu jeszcze trochę i trafisz do perełek.

Próbujesz rozwiązać problem, który sam sobie stworzyłeś. Dodatkowo stworzyłeś też kilka innych problemów, z których obecnie na razie nie zdajesz sobie sprawy.
Bo przy Twoim perwersyjnym podejściu trzeba:

  1. zawsze pobierać całą tabelę, nawet jeśli ma miliard rekordów, inaczej nie dojdziesz do "numerów" wierszy po numerach z grida.
  2. co w sytuacji, gdy kilka rekordów będzie miało wszystkie takie same wartości?
0
miki10194 napisał(a):

@Shalom za każdym razem używając

SELECT * FROM nazwa_tabeli

wyświetla mi się cała zawartość tabeli w tej samej kolejności, w jakiej wstawiłem pojedyncze rekordy używając insertów.

I nie dziwota. Jak robisz takiego selecta bez żadnych warunków to optymalizator kosztowy właściwie zawsze zrobi full-table-scan bo w tej sytuacji nie ma sensu pobierać danych w inny sposób. Więc odczyta je w kolejności ich występowania na dysku. Niemniej nie masz żadnej gwarancji takiego zachowania i nie masz też gwarancji że położenie danych na dysku nie ulegnie zmianie. Szczególnie kiedy usuwasz dane z tabeli. Bo szbd nie bawi się w "przesuwanie" danych na wolne miejsca tylko może te wolne miejsca wypełniać nowymi rekordami.

tylko musiałbym zaznaczać tylko pola w pierwszej kolumnie, a chciałem to zrobić bez takiej potrzeby.

To jest bzdura. Skoro masz zaznaczonego Cella to znasz jego wiersz i kolumnę. Wczytujesz więc po prostu ręcznie ID z tego wiersza i tyle. Gdzie widzisz problem? o_O

0

Już nie widzę problemu. Czasem przyda się trochę pocisku żeby rozjaśnić myślenie :-). Zrobię to na id.

		table.getModel().addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(TableModelEvent arg0) {

				if(table.getCellEditor() == null) 
					System.out.println("Nieedytowana komórka!");
				else {
					int selectedRow = table.getSelectedRow(); int selectedColumn = table.getSelectedColumn(); String columnName = table.getColumnName(selectedColumn);
					Object fieldName = table.getValueAt(selectedRow, selectedColumn);
					Object idName = table.getValueAt(selectedRow, 0);
					String idColumnName = table.getColumnName(0);
					String query = "UPDATE "+tableName+" SET "+columnName+" = "+"'"+fieldName+"'"+" WHERE "+idColumnName+" = "+idName;
					rs = null;
					try {
						rs = sendQuery(query);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
			}
		});

Zrobiłem coś takiego i mi edytuję i komórki w JTable i w Bazie.
Dzięki wszystkim za pomoc :)

0

ZASUGEROWAŁEM SIĘ PIERWSZYMI LINIAMI KODU, teraz wszystko jest ok, pozdrawiam :)

Chłopie, robisz to czego nie chciałeś robić.Musisz kliknąć w ID, żeby dostać ID.

 int selectedColumn = table.getSelectedColumn();

Ustaw sobie id na stałe na kolumnie 0, i wtedy gdzie użytkownik na ten wiersz nie kliknie zrób coś takiego:

 Object fieldName = table.getValueAt(selectedRow, **0**);

Niech sobie użytkownik klika gdzie chce...

Pozdrawiam

0

@abrakadaber, @Shalom jak już to rownum, który jest unikalny na zapytaniu, ale czytelniejszy.

@miki10194 za bardzo kombinujesz to raz, bo w tabeli prezentujesz dane, ale nigdzie nie trzymasz informacji o tym co te dane w rzeczywistości reprezentują. Inaczej mówiąc wyświetlasz sobie kolejne rekordy, ale nie masz informacji o obiektach z których one pochodzą.

  1. zamiast bezpośrednio przepisywać wyniki zapytania do tabeli wprowadź obiekty DTO do których będzie mapowany wynik zapytania
  2. Zapoznaj się z https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#data
  3. a następnie z https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#modelchange oraz https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editrender

Problem sam się rozwiąże dzięki zastosowaniu prawidłowego podejścia.

0

miał być komentarz ale się nie zmieściło :p
Nie - rekord dostaje rowid, który jest zapisywany! w momencie dodania rekordu. Po usunięciu rekordu jego rowid wraca do puli wolnych i może zostać przypisany innemu rekordowi. Jednak od momentu wstawienia rekordu do bazy aż do jego usunięcia rekord ma zawsze TEN SAM rowid. Odrębnym przypadkiem jest tutaj eksport i import bazy - ponieważ rowid jest ściśle związany z fizycznym położeniem rekordu na dysku to po imporcie może mieć inny rowid. Natomiast rownum to jest tylko i wyłącznie kolejność rekordu w wyniku zapytania.

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