ID ostatnio dodanego rekordu z bazy MSSQL.

0

Witam,
Wprowadzam do bazy danych jakieś dane poprzez INSERT i chcę po wprowadzeniu tych danych otrzymać ich ID utworzone automatycznie przez serwer MSSQL.
Wiem jak to zrobić w samym SQL ale nie wiem jak wydobyć to ID za pomocą Delphi. Jak mam w Delphi wyświetlić dane zwracane przez scope_identity() idx
Mój kod:

if data1.MSSQL1.Connected then
        SQLQuery1.Close;
        SQLQuery1.SQL.Clear;
        SQLQuery1.SQL.Add('INSERT  INTO dbo.t_tw (nr_kodowy, nazwa, il_w_partii, nr_dok_prze, nr_partii, data_dos)VALUES('''+ EditSzukajRAC.Text + ''','''+EditRACName.Text+''','''+EditRACIloscPartii.Text+''','''+EditRACNrDokPrzew.Text+''','''+EditRACNrPartii.Text+''','''+EditRACDataDostawy.Text+'''); SELECT scope_identity() idx');

    try
        SQLQuery1.ExecSQL;
        showmessage(''+SQLQuery1.FieldByName('idx').AsString+'');
    except
        ShowMessage('Wystąpił błąd podczas wstawienia rekordu Form4');
    end;
    SQLQuery1.Active := False;
 

Już siedzę nad tym trzy dni i głowami pęka, proszę o wskazówkę co zrobić. Dziękuję.

0

Nie jestem specem od delphi ale dodaj na początku zapytania:

Set nocount on;

Dodatkowo execsql nie zwraca danych, to do weryfikacji od tych co się znają. Ale chyba trzeba zmienić na open...

0

@Panczo: , a ja nie jestem specem od MSSQL :) ale insert czy update jako podstawowa komenda w zapytaniu realizowanym za pomocą bazodanowych komponentów Delphi wymaga execsql
open to przy select.
a autor chyba mocno zamieszał budując zapytanie

0

Jaki masz komunikat błędu? A może nie masz błędu tylko ID nie pokazuje? Doprecyzuj.

1

obsługa wyjątku zastosowana przez autora maskuje pierwotny wyjątek
zamiast tego

 except
        ShowMessage('Wystąpił błąd podczas wstawienia rekordu Form4');
 end;

lepiej tak to zrobić

except
    on e:exception do 
         ShowMessage('Wystąpił błąd podczas wstawienia rekordu Form4 ' +#13+#10+e.message);
end
4

Spróbuj tak:

'INSERT INTO tabela (wartosci....) ' +
'OUTPUT INSERTED.nazwa_pola_z_ID ' +  //zwraca wstawione ID
'VALUES ' +
'( wartosci......)';
Query.OpenOrExecute;

if Query.RecordCount = 1 then
  Result := Query.FieldByName('nazwa_pola_z_ID').AsInteger;

i zacznij używać parametryzowanych zapytań oraz kłania się obsługa wyjątków.

0
grzegorz_so napisał(a):

@Panczo: , a ja nie jestem specem od MSSQL :) ale 'insert' czy 'update' jako podstawowa komenda w zapytaniu realizowanym za pomocą bazodanowych komponentów Delphi wymaga 'execsql'
'open' to przy 'select'.
a autor chyba mocno zamieszał budując zapytanie

Nie wiem, czy zamieszał, ale tam ostatni jest select, jako, że na Delphi znam się jak kot na gwiazdach to zrobiłem research i tu potwierdza się różnica między execsql, a open: http://stackoverflow.com/questions/33280954/get-last-row-data-after-insert-into-using-delphi-adoquery

Ale upierać się nie będe ;)

Ale to też ciekawe, że minuta z google daje dokładnie odpowiedź na pytanie, a OP piszę, że męczy się z tym 3 dni...

0

Dziękuję Panowie,
Dziękuję wszystkim za zainteresowanie i pomoc, Lampasss dziękuję za podpowiedź, działa - tak przy okazji dopiero uczę się SQL i odkrywam możliwości Delphi. Grzegorz_so dziękuję za podpowiedź odnośnie wyświetlenia wyjątków.

0

@Panczo: , w delphi i bazodanowych 'datasetach' reguły są proste , jeśli odczyt danych z bazy to zawsze 'open', a w każdym innym przypadku "execsql"

0

@grzegorz_so: jak, pokazał @lampasss jest jeszcze 3 droga: Query.OpenOrExecute :)

0

może i masz rację:) Zależy od tego jakie komponenty bazodanowe są w użyciu . Te z których ja do tej pory korzystałem przy odczycie zawsze wymagały użycia 'open' , a w każdej innej sytuacji 'execsql'

0

@Panczo : z tego co znalazłem w necie, to metodę OpenOrExecute implementują komponenty FireDac będące częścią środowiska Delphi od wersji XE5

0

@grzegorz_so: ok, ja nie piszę w Delphi, a OP nie zdefiniował z jakich komponentów korzysta, założyłem tylko, że skoro przekazuje w zapytaniu kilka instrukcji to istotne jest czy ona coś zwraca. Dlatego zwróciłem uwagę, na Open, a nie ExecSQL.

3

Panowie ja tylko tak w gwoli ścisłości. Jeśli pytacz używa FireDAC, to bez względu czy odpali procedurę bazodanową, która robi insert, czy wali inserta z kodu zwykłym poleceniem insert i bez względu na Open/ExecSQL/ExecProc to komponent TADCOnnection/TFDConnection w zależności od wersji delphi ma możliwość zwrócenia ostatniej wartości sekwencji po jej podaniu ;)
http://docwiki.embarcadero.com/Libraries/XE8/en/FireDAC.Comp.Client.TFDCustomConnection.GetLastAutoGenValue

0

można też tak z podaniem z której tabeli wyciągamy ID

 format('SELECT ident_current(''%s'') AS IdNewDok', [nazwa_tabeli]);

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