Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

VB .NET 2012 - Pobranie ostatniego autonumeru z tabeli w bazie typu mdb

janek1111 30 Mar 2014 15:03 1350 17
  • #1 30 Mar 2014 15:03
    janek1111
    Poziom 13  

    Witam

    Mam problem opisany jak w temacie. Używam do tego następującego kodu:

    Kod: vbnet
    Zaloguj się, aby zobaczyć kod




    , ale program zawsze zwraca wartość równą 0 pomimo, że w auto-numerowanej kolumnie bazy znajdują się ok 4000 rekordów. Proszę o sugestie i wskazanie dlaczego ów kod nie przynosi oczekiwanych rezultatów...

    Pozdrawiam

    0 17
  • #2 30 Mar 2014 16:25
    cepelia
    Poziom 20  

    Kolumna w bazie z nr wiersza jest unique czy integer ??

    Spróbuj max() dostaniesz największy nr w kolumnie (nie wiem jak będzie się zachowywał z kolumną typu unique)...

    0
  • #3 30 Mar 2014 17:02
    janek1111
    Poziom 13  

    Kolumna z nr jest AUTOINCREMENT, czyli wg mnie uniqe. Z max() + 1 już próbowałem i działa, ale nie tak jak powinno, tzn. np., gdy zostanie usunięty ostatni rekord w tabeli bazy o nr 5, to pomimo tego nowy dodany będzie miał nr 6. A max() naliczy mi w tym przypadku 5, a nie 6...

    0
  • #4 30 Mar 2014 18:05
    cepelia
    Poziom 20  

    Nie trzeba gdybać tylko sprawdzić... poza tym nie bardzo rozumiem twój tok rozumowania... chcesz ostatni wiersz to dostajesz id ostatniego wiersza nie ważne że nie będzie po kolei... tak prawdę mówiąc nie ma znaczenia czy będzie po kolei, ważne żeby zawsze było inne i zawsze większe od poprzedniego...

    Poza tym piszesz że nr wiersza to np 5 czyli integer a nie unique.

    0
  • #5 30 Mar 2014 20:01
    rufek90
    Poziom 24  

    W MySQL będzie to tak:

    Kod: mysql
    Zaloguj się, aby zobaczyć kod


    To pokazuje ten id, który się nada, gdy dodasz następny wiersz.

    0
  • #6 30 Mar 2014 21:40
    marcinj12
    Poziom 40  

    Polecenie

    Kod: sql
    Zaloguj się, aby zobaczyć kod
    nie ma składni umożliwiającej podanie jako parametru tabeli - wywołuje się je pisząc po prostu tak, jak jest wyżej.
    Nie służy ono do ustalenia ostatniej wartości pola autonumerowania w tabeli, a podaje ostatnią wartość zwróconą przez generator autoinkremantacji w danym połączeniu.
    Oznacza to tyle, że dopóki nie użyjesz w jednej "sesji" połączenia przynajmniej jednego INSERT, to zwracana wartość będzie zawsze równa 0.

    0
  • #7 30 Mar 2014 22:25
    cepelia
    Poziom 20  

    Coś czuję że kolega chce ręcznie łączyć krotki...

    0
  • #8 30 Mar 2014 22:36
    janek1111
    Poziom 13  

    Dla jasności napiszę, że jest mi konkretnie potrzebne do tego, aby wiedzieć przed dodaniem do bazy nowego rekordu, jaki będzie jego autonumer ID. Teraz kombinuję z DAO TDF.TableDefs , ale widzę, że tu i też nic konkretnego nie będzie w tym zakresie. A dodawanie do bazy danych nowego rekordu po to żeby sprawdzić ostatni auto numer mi się jakoś nie widzi...

    0
  • #9 30 Mar 2014 22:56
    marcinj12
    Poziom 40  

    janek1111 napisał:
    Dla jasności napiszę, że jest mi konkretnie potrzebne do tego, aby wiedzieć przed dodaniem do bazy nowego rekordu, jaki będzie jego autonumer ID.
    A do czego Ci ta wiedza potrzebna? Nie wiesz i nie będziesz tego wiedział na 100%, dopóki rekordu faktycznie nie dodasz.

    0
  • #10 30 Mar 2014 23:00
    rufek90
    Poziom 24  

    marcinj12 Bzdura, kilka postów wyżej jest mój post z rozwiązaniem, sprawdzone pod MySQL - mam nadzieję, że będzie pasować.

    0
  • #11 30 Mar 2014 23:04
    marcinj12
    Poziom 40  

    rufek90 napisał:
    marcinj12 Bzdura, kilka postów wyżej jest mój post z rozwiązaniem, sprawdzone pod MySQL - mam nadzieję, że będzie pasować.
    A konkretnie z czym bzdura?? Kod pod MySQL do niczego się autorowi nie przyda, bo pytał o MS Access.

    0
  • #12 30 Mar 2014 23:24
    rufek90
    Poziom 24  

    marcinj12 napisał:
    rufek90 napisał:
    marcinj12 Bzdura, kilka postów wyżej jest mój post z rozwiązaniem, sprawdzone pod MySQL - mam nadzieję, że będzie pasować.
    A konkretnie z czym bzdura?? Kod pod MySQL do niczego się autorowi nie przyda, bo pytał o MS Access.


    Fakt, autor nie określił wprost, a ja nie zwróciłem uwagi na connection string.

    Jeżeli Access nie pozwala tego sprawdzić w podobny sposób, to pozostaje zapuścić inserta, zapisać ID, usunąć ostatni wpis i wtedy wiadomo, że kolejny będzie miał ID o jeden większe... Tyle, że cena uzyskania ID w ten sposób jest dość wysoka.

    Można też rozwiązać to w ten sposób: puścić inserta w momencie, gdy potrzebne ID. I później tego ostatniego inserta już nie usuwać, tylko zrobić update ostatniego rekordu przy następnym insercie

    Oba rozwiązania są niestety wpłyną negatywnie na wydajność i mogą narobić bałaganu w bazie.

    Myślę, że najmniej inwazyjnym i dość pewnym rozwiązaniem będzie nie usuwanie rekordów 'fizycznie' z bazy, a jedynie przestawianie flagi na 'del' i nie branie rekordów z 'del' podczas selectów. To z kolei wymaga trochę więcej pracy przy przeprojektowaniu zapytań. Jestem zwolennikiem tworzenia takich flag zamiast trwałego usuwania, bo czasem się zdarza, że trzeba przywrócić na szybko coś, co ktoś usunął.

    0
  • #13 30 Mar 2014 23:43
    marcinj12
    Poziom 40  

    rufek90 napisał:
    Jeżeli Access nie pozwala tego sprawdzić w podobny sposób, to pozostaje zapuścić inserta, zapisać ID, usunąć ostatni wpis i wtedy wiadomo, że kolejny będzie miał ID o jeden większe...
    Nie do końca wiadomo - jak już pisałem, Id pewne będzie jedyne wtedy, kiedy rekord znalazł się w bazie, i do jego odczytania można użyć choćby @@IDENTITY.
    Wszystkie inne sposoby na uzyskanie ID przed wstawieniem rekordu są jedynie "domysłami", które nie jest rozsądnie stosować w jakimkolwiek systemie, z którego korzysta więcej niż jedna osoba.
    Nawet, jeżeli uzyskasz (w jakikolwiek sposób) wiedzę o kolejnym numerze ID, może się zdarzyć, że przed wykonaniem właściwego INSERTA wykorzystującego to ID (to mogą być mili lub mikrosekundy - ale jakiś czas to jest) inny użytkownik wstawi swój rekord, i twój faktyczny numer ID będzie inny, niż odczytany. Prawdopodobieństwo takiej sytuacji rośnie tym bardziej, im więcej użytkowników korzysta równolegle z bazy. A skoro nie jest to metoda na 100% pewna, to nie powinno się jej stosować, żeby nie kusić losu (tym bardziej, że można inaczej). Z tego też powodu nie powinno się tego używać do tworzenia relacji przy jednoczesnym wstawianiu do dwóch tabel - mam podejrzenia, że autor może właśnie to chcieć zrobić...

    Podsumowując - obstaję przy tym, że nie ma potrzeby uzyskiwania ID rekordu przed jego wstawieniem. Bez poznania kontekstu, w którym autor (zapewne niepotrzebnie) chce to stosować, nie można doradzić nic więcej oprócz tego, że trzeba to zrobić inaczej...

    0
  • #14 31 Mar 2014 06:02
    cepelia
    Poziom 20  

    Zgadzam się z przedmówcą...

    Posiadanie tej tajemnej wiedzy jest że tak powiem mocno niekonieczne. Dodam że nie ma nawet pewności czy po id 10 nie wskoczy id 300 co już niejednokrotnie widziałem (czemu?? nie mam zielonego pojęcia).
    Powtórzę jeszcze raz, po wykonanym insercie robisz maxa i masz id ostatniego rekordu w bazie, jeśli użyjesz transakcji masz pewność że to twój rekord.

    0
  • #15 31 Mar 2014 21:05
    janek1111
    Poziom 13  

    W moim przypadku połączenie do bazy będzie miał zawsze tylko jeden użytkownik. To co wyżej przeczytałem ma sens i widzę, że będę musiał wprowadzić pewne zmiany. Ale żeby nie zakładać nowego tematu, to mam jeszcze pytanie w drugą stronę. A mianowicie jak sprawdzić ile rekordów z bazy (tabeli) zostało usuniętych?

    0
  • #16 31 Mar 2014 22:21
    marcinj12
    Poziom 40  

    janek1111 napisał:
    A mianowicie jak sprawdzić ile rekordów z bazy (tabeli) zostało usuniętych?
    Usuniętych kiedy i w jaki sposób? cmd.ExecuteNonQuery(); dla polecenia DELETE zwraca ilość usuniętych rekordów, jeśli o to chodzi.

    0
  • #17 31 Mar 2014 22:46
    janek1111
    Poziom 13  

    Nie podczas samego usuwania, ale w ogóle, tzn. suma wszystkich usuniętych rekordów z tabeli sprawdzana w danym momencie.

    0
  • #18 31 Mar 2014 22:51
    marcinj12
    Poziom 40  

    Niektóre systemy bazodanowe (np. PostgreSQL) prowadzą takie statystyki, ale nie sądzę, aby w przypadku Accesa też tak było. Jeżeli tego potrzebujesz, to musisz sam je prowadzić, przy usuwaniu zwiększając licznik w jakiejś tabeli pomocniczej (koniecznie w transakcji z samym usuwaniem), ew. jak pisał ktoś wcześniej - nie usuwać rekordów fizycznie, a jedynie oznaczyć je flagą - wtedy można je zliczyć. Zdaje się triggerów też w Accesie się nie zrobi, więc chyba tylko to pozostaje.

    0