![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Получение сгенерированного акцессом ключа для новой записи [D7]
boalse © (2007-11-11 09:32:00)Здравствуйте. Есть база данный .mdb, в ней таблица org с первичный ключем ID_ORG, являющийся счетчиком. Таблица org связана отношением один ко многим с таблицей adr, тоесть с одной записью из org может быть связано много записей из adr по вторичному ключу ID_ORG в adr. Эту базу использует внешняя программа, которую я пишу на Delphi 7 (компоненты ADO). Теперь допустим через мою программу добавляется запись в таблицу ORG, при этом первичный ключ присваивается ей автоматически, так как это счетчик. Как мне добавлять запись таким образом, чтобы я мог сразу узнать значение этого сгенерированного автоматически ключа? Это значение мне нужно чтобы добавлять записи в adr и сразу указывать что эта запись связана именно с новой записью из org.
Написал в акцессе запрос на добавление:
PARAMETERS POrgName Text ( 225 );
INSERT INTO Org ( NAME )
VALUES (POrgName);
Вызываю этот запрос из делфи, всё нормально, запись добавляется, но вот поизящней как получить значение поля ID_ORG не могу придумать. Можно конечно взять последнюю запись в таблице какимнибудь запросом, считать её ключ и сказать что это и есть то, что мне нужно, но это уже уродливо, на самый крайний случай оставлю. Как вообще поступают в подобных случаях?
Суть в чем, пользователь добавляет новую организацию через форму, в этой же форме он может добавить ей адреса, но как я буду присваивать эти адреса новой организации, если я не знаю её ключа.
Anatoly Podgoretsky (2007-11-11 12:39:00) [1]При работе с IDENTITY всегда надо думать об области ее действия.
Например в первом приближение это соединение, далее пакет.
В MS SQL надо что бы запрос на вставку и запрос на получение ИД должен быть в одном пакете. Для Акцесс возможно достаточно, что бы было одно соединение. Легко проверяется.
boalse (2007-11-11 11:56:00) [2]Если назначать не ConnectionString, а Connection, получается та ситуёвина, про которую я говорил.
Palladin, спасибо большое, я прозрел :)
Palladin (2007-11-11 11:47:00) [3]учитывая, что без назначенного Connection, но назначенного ConnectionString TADOQuery будет создавать свой собстенный экземпляр TADOConnection
Palladin (2007-11-11 11:46:00) [4]
> boalse © (11.11.07 11:35) [12]
Смотри фенечку
var
q1,q2:TADOQuery;
n1,n2:Integer;
begin
q1:=TADOQuery.Create(Nil);
q1.ConnectionString:=ADOConnection1.ConnectionString;
q2:=TADOQuery.Create(Nil);
q2.ConnectionString:=ADOConnection1.ConnectionString;
q1.SQL.Text:='insert into org (name) values (''1'')';
q1.ExecSQL;
q2.SQL.Text:='insert into org (name) values (''2'')';
q2.ExecSQL;
q1.SQL.Text:='select @@Identity';
q1.Open;
n1:=q1.Fields[0].AsInteger;
q1.Close;
q2.SQL.Text:='select @@Identity';
q2.Open;
n2:=q2.Fields[0].AsInteger;
q2.Close;
ShowMessage(IntToStr(n1)+':'+IntToStr(n2));
q1.Free;
q2.Free;
end;
и вот такую
var
q1,q2:TADOQuery;
n1,n2:Integer;
begin
q1:=TADOQuery.Create(Nil);
q1.Connection:=ADOConnection1;
q2:=TADOQuery.Create(Nil);
q2.Connection:=ADOConnection1;
q1.SQL.Text:='insert into org (name) values (''1'')';
q1.ExecSQL;
q2.SQL.Text:='insert into org (name) values (''2'')';
q2.ExecSQL;
q1.SQL.Text:='select @@Identity';
q1.Open;
n1:=q1.Fields[0].AsInteger;
q1.Close;
q2.SQL.Text:='select @@Identity';
q2.Open;
n2:=q2.Fields[0].AsInteger;
q2.Close;
ShowMessage(IntToStr(n1)+':'+IntToStr(n2));
q1.Free;
q2.Free;
end;
исполни, и пойми в контексте чего работает @@Identity
:)
boalse (2007-11-11 11:37:00) [5]тут неизвестна причина (17), т.к. вариантов довольно много, но ясно, что 0 читается из другого экземпляра обьекта, не того где делается инсерт.
а, тоесть Identity она только в контексте экземпляра отдельного работает. Тогда похоже точно глупость ляпнул в предыдущем :)
boalse (2007-11-11 11:35:00) [6]Palladin, спасибо, это подходит. Но вопрос возник. q.ExecSQL и q.Open, это всё в одной транзакции происходит? То есть не получится ли так, что сначало один пользователь вызывал q.ExecSQL и добавилась новая запись, потом почти одновременно другой пользователь тоже вызвал q.ExecSQL и добавил ещё одну запись, ну и наконец первый юзер вызывает q.Open и что он получает, случайно не идентификатор на новую запись второго пользователя? Такая ситуация возможна, или я глупость сказал?
sniknik (2007-11-11 11:33:00) [7]sniknik © (11.11.07 11:26) [10]
+
т.е. на каждое подключение Jet создает свой экземпляр COM обьекта. естественно все значения переменных одного экземпляра, не видны в другом (имеют другие значения).
тут неизвестна причина (17), т.к. вариантов довольно много, но ясно, что 0 читается из другого экземпляра обьекта, не того где делается инсерт.
sniknik (2007-11-11 11:26:00) [8]> что ему ноль возвращается на идентити...
ноль это от того, что запрос на вставку и получение в разных контентах, например с разными "конекшионами", или с переконектом между этими запросами, или... в общем в 17й строке.
Palladin (2007-11-11 11:23:00) [9]
> sniknik © (11.11.07 11:20) [7]
да это я про то, что ему ноль возвращается на идентити...
ошибка то про инструкции понятна :)
sniknik (2007-11-11 11:22:00) [10]> зачем вообще PARAMETERS? почему бы так не вставлять?
одна из форм синтаксиса в accecc. очень "любима" мастером запросов в самом аксессе.
sniknik (2007-11-11 11:20:00) [11]> значит у тебя нет первичного ключа и/или его тип не "Счетчик"
не, не изза этого, тут ему правильно в проигнорированной ошибке вернуло -"дальше инструкций быть не должно.", в аксессе все "однозапросно" (даже "процедуры").
> Пробовал вызывать SELECT @@IDENTITY отдельным запросом сразу после добавления, возвращает всегда 0.
ошибка в 17й строке.
Palladin (2007-11-11 11:17:00) [12]зачем вообще PARAMETERS? почему бы так не вставлять?
q:TADOQuery;
nNewID:Integer;
q.sql.text:='insert into org (name) values (:POrgName)';
q.Parameters.ParamByName('POrgName').Value:='OrgName';
q.ExecSQL;
q.sql.text:='select @@Identity';
q.Open;
nNewID:=q.Fields[0].AsInteger;
q.Close;
Palladin (2007-11-11 11:12:00) [13]значит у тебя нет первичного ключа и/или его тип не "Счетчик"
boalse (2007-11-11 11:10:00) [14]PARAMETERS POrgName Text ( 225 );
INSERT INTO Org ( NAME )
VALUES (POrgName)
SELECT @@IDENTITY
Так чтоли? В акцесе не работает, пишет ошибка синтексиса, мол после VALUES (POrgName) должна стоять точка с запятой и дальше инструкций быть не должно. Пример посмотрел в хелпе для SQL Server 2000.
Пробовал вызывать SELECT @@IDENTITY отдельным запросом сразу после добавления, возвращает всегда 0.
sniknik (2007-11-11 10:14:00) [15]> Какую переменную, в каком присваивании?
в этом
> но как я буду присваивать эти адреса новой организации, если я не знаю её ключа.
вот где ты не знаеш что присваивать, но чтото присваиваеш, там и ставь @@IDENTITY.
> что такое @@IDENTITY?
F1 в нужном месте полностью ответит на твой вопрос.
boalse (2007-11-11 10:08:00) [16]А подробнее можно?
>либо прям в присваивании переменную использовать
Какую переменную, в каком присваивании?
>SELECT @@IDENTITY
что такое @@IDENTITY?
sniknik (2007-11-11 09:51:00) [17]узнать
SELECT @@IDENTITY
либо прям в присваивании переменную использовать, если оно запросом делается.