logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Delphi 7, Firebird 2.1 - Jak poprawnie autonumerować ID w triggerze?

piusik 08 Cze 2015 00:29 1320 10
REKLAMA
  • #1 14753371
    piusik
    Poziom 13  
    Posty: 82
    Ocena: 19
    Mam pytanie, bo nigdzie nie mogę znaleźć poprawnej recepty, jak wykonać poprawne autonumerowanie pisząc w Delphi i używając komponentów Interbase, w oparciu o RDBMS Firebird, wykorzystując generatory i używając trigera.
    (Delphi 7, Firebird 2.1)
    Jeżeli chodzi o Firebird, jest sprawa jasna, lecz nie wiem jak wykonać to po stronie Delphi. Nie chodzi mi o to jak zbudować program, tylko jakich metod użyć.
    Powiedzmy, że wpisanie wartości liczby porządkowej ID musi wykonać Firebird w trigerze, ale Delphi "krzyczy", że potrzebna jest wartość ID przed wykonaniem INSERTa.
    Więc posiłkowo wartość tą odczytuje odczytując ilość wierszy, lecz nie jest to poprawne i jeśli zacznie pracować dwóch klientów to program będzie pracować niepoprawnie.
  • REKLAMA
  • #2 14754938
    Jaca
    Poziom 32  
    Posty: 1332
    Pomógł: 239
    Ocena: 217
    Np za pomocą takiego kodu wyzwalacza:

    Kod: SQL
    Zaloguj się, aby zobaczyć kod

    Potem przy INSERT podajesz 0 dla pola REC_ID a Firebird sam nada kolejny numer:

    Kod: SQL
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #3 14755165
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    A kolumnę masz zaznaczoną, jako autoinc?

    Powiem szczerze, że nie przepadam za tym schematycznym podejściem do baz - zdecydowanie wolę operować zapytaniami, niż pozwalać komponentom na określanie struktury i używać ich właściwości do operacji. Trochę lepiej jest to już we FireDACu zrobione (od XE2 bodaj).
  • REKLAMA
  • #4 14756103
    piusik
    Poziom 13  
    Posty: 82
    Ocena: 19
    W starej siódemce jest głupkowato. Jak dodaje Insertem, to wiersz jest na samej górze. W SBstringgridzie trzeba się posiłkować w Eventach że przed insertem zjedź na sam dół.
    Dodam pliki w wersjki 7 enterprise może ktoś już przekopał to, popatrzy na konfiguracje i wyłuska babola albo pomoże odpowiednią metodą.
  • Pomocny post
    #5 14756387
    Konto nie istnieje
    Konto nie istnieje  
  • #6 14757739
    arnoldziq
    VIP Zasłużony dla elektroda
    Posty: 5376
    Pomógł: 789
    Ocena: 300
    Ja w Delphi5 odczytuję najpierw kolejne id z odpowiedniego generatora a potem
    dodaję rekord zwykłym zapytaniem.

    Stwórz sobie generator. np;
    Kod: SQL
    Zaloguj się, aby zobaczyć kod

    A potem tylko odczytuj ID wywołując taką procedurę :
    Kod: SQL
    Zaloguj się, aby zobaczyć kod
  • #7 14758990
    piusik
    Poziom 13  
    Posty: 82
    Ocena: 19
    Kolego arnoldziq coś podobnego co kolega majeranek53 i ma to sens bo numer nadaje kolejno serwer a nie dwóch klientów na raz ten sam numer :-), szkoda że trzeba mocno wymyślać i obsługiwać wyjątki własnym mózgiem a komponentów setki wokół i nie ogarniają kuwety.
    A "głupi" MS Acces robi to tak łatwo i prosto z tego co pamiętam z lekcji MSOffice.

    Jednak rodzi się pytanie, skoro generator się dodał już to jak cofnąć transakcję.

    Chociaż dla mnie ważniejsze aby dwóch klientów nie updatowali na wspólnym id niż mają być luki w kolejności liczb ID.
    Najlepiej żeby Delphi olało numer ID bo serwer wypełni sam Generatorem + triger ale nie pokazywał głupot w tabeli, bo eksperymentuje teraz w ten sposób to Id wpisuje jak to nie wiem, serwer robi poprawnie swoje. Poprawne wyświetlenie po ponownym połączeniu z bazą. A z transakcjami to już nawet nie zaczynam....
  • #8 14759804
    arnoldziq
    VIP Zasłużony dla elektroda
    Posty: 5376
    Pomógł: 789
    Ocena: 300
    piusik napisał:
    Jednak rodzi się pytanie, skoro generator się dodał już to jak cofnąć transakcję.
    Cofasz transakcję za pomocą Transaction.Rollback.
    Niestety, z generatorem nie jest tak prosto, bo nie wiesz ilu klientów w "międzyczasie" z niego skorzystało.

    Jeżeli zadeklarujesz pole ID jako integer:
    Kod: SQL
    Zaloguj się, aby zobaczyć kod
    To masz miejsce na ponad 4 miliardy (od -2^31 (-2,147,483,648) do 2^31 - 1 (2,147,483,647)) identyfikatorów. Nawet gdy użyjemy tylko liczb dodatnich, to i tak daje nam to ponad 2 miliardy unikalnych identyfikatorów. Zazwyczaj to wystarczy do dowolnych zastosowań, nawet gdy 90% to te luki w numeracji. Więc lukami raczej bym się nie przejmował.

    Można pole ID wypełnić trigger-em, tak jak zaproponował to wcześniej któryś z kolegów. Rozwiązanie szybkie, pewne i dość proste do zastosowania.
    Ma tylko jedną, według mnie zupełnie niedopuszczalną wadę: nie znasz ID które zostanie przydzielone.
    Niby nie jest to duża wada, ale jeżeli masz kilka tablic w których masz to samo ID zapisać, to moja metoda upraszcza i przyspiesza ten proces (w moim wypadku, w niektórych bazach nawet kilkunastokrotnie). Gdy użyjesz trigger-a, po każdym zapisie będziesz musiał dany rekord znaleźć i odczytać tylko po to, żeby poznać ID -> zupełnie bez sensu.
  • #9 14760291
    piusik
    Poziom 13  
    Posty: 82
    Ocena: 19
    Czy komponent IBTransaction kontroluje działanie trigera na serwerze?
    Wynika stąd że najlepiej wszystko wykonywać za pomocą procedur w bazie...
    Potem poprostu zwróci ID lub odświeżyć tabelę z naszym nowym rekordem na dole.
  • Pomocny post
    #10 14760331
    arnoldziq
    VIP Zasłużony dla elektroda
    Posty: 5376
    Pomógł: 789
    Ocena: 300
    piusik napisał:
    Czy komponent IBTransaction kontroluje działanie trigera na serwerze?
    Serwer kontroluje działanie trigger-ów na serwerze. Możesz tylko zastosować odpowiedni trick, żeby ja czasami omijać, gdy nie są potrzebne.
    piusik napisał:
    Wynika stąd że najlepiej wszystko wykonywać za pomocą procedur w bazie...
    Wtedy masz największą kontrolę nad bazą.
    piusik napisał:
    Potem poprostu zwróci ID lub odświeżyć tabelę z naszym nowym rekordem na dole.
    Jeżeli mogę coś doradzić, to przestań myśleć o bazie SQL w kategoriach "na górze", "na dole". To nie jest plik DBase gdzie możesz "palcem" wskazać gdzie znajduje się pierwszy a gdzie ostatni rekord.
    To czy obecnie dodawany rekord znajduje się na "dole" czy na "górze" to po pierwsze nie ma żadnego znaczenia, po drugie zależy od wielu czynników jak np. Primary Key danej tabeli.
    Baza SQL zapisuje dane w odpowiednim formacie, a to twoim zadaniem jest stworzenie takiego zapytania, żeby dane ułożyły się w odpowiednim "kierunku" i kolejności.
  • REKLAMA
  • #11 14946651
    piusik
    Poziom 13  
    Posty: 82
    Ocena: 19
    W programie IBexpert do zarządzania Firebirdem są gotowe skrypty do generowania konkretnych procedur (insert,update...) działające w RDBMS-ie czyli w delphi wywołuje procedurę ze Stored procedure najlepiej i serwer wykonuje np. inserta i zwraca ID.
    Dochodzie jeszcze temat Transakcji.
    Gdzie kontrolować transakcje? Czyżby po stronie klienta z różnymi stopniami izolacji?
    W tej fazie wiedzy na temat baz klient - serwer wychodzi na to że trzeba oprócz stworzenia tabel, generatorów, trigerów i procedur które ma obsługiwać RDBMS pomyśleć jeszcze nad tym do jakich opcji te struktóry mają służyć klientowi i ułożyć po stronie klienta transakcje, która ma zabezpieczyć przed bałaganem w struktórach danych a to nie jest już takie proste i duuużo wychodzi w "praniu".
    ps.
    A można układać transakcje po stronie serwera?

Podsumowanie tematu

✨ W dyskusji poruszono problem autonumerowania identyfikatorów (ID) w bazie danych Firebird 2.1 przy użyciu Delphi 7. Użytkownicy sugerują wykorzystanie triggerów oraz generatorów do automatycznego przypisywania wartości ID. Przykładowy kod triggera tworzy nowy identyfikator, gdy pole REC_ID jest puste lub mniejsze od zera. Wskazano również na konieczność odpowiedniego zarządzania transakcjami oraz na różnice w podejściu do obsługi baz danych w Delphi w porównaniu do innych systemów, takich jak MS Access. Użytkownicy podkreślają, że serwer powinien zarządzać ID, aby uniknąć konfliktów przy równoczesnym dostępie wielu klientów. Wskazano na możliwość użycia procedur składowanych do obsługi operacji na bazie danych.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA