Форум: "Начинающим";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];
ВнизПолучение сгенерированного акцессом ключа для новой записи Найти похожие ветки
← →
boalse © (2007-11-11 09:32) [0]Здравствуйте. Есть база данный .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 не могу придумать. Можно конечно взять последнюю запись в таблице какимнибудь запросом, считать её ключ и сказать что это и есть то, что мне нужно, но это уже уродливо, на самый крайний случай оставлю. Как вообще поступают в подобных случаях?
Суть в чем, пользователь добавляет новую организацию через форму, в этой же форме он может добавить ей адреса, но как я буду присваивать эти адреса новой организации, если я не знаю её ключа.
← →
sniknik © (2007-11-11 09:51) [1]узнать
SELECT @@IDENTITY
либо прям в присваивании переменную использовать, если оно запросом делается.
← →
boalse © (2007-11-11 10:08) [2]А подробнее можно?
>либо прям в присваивании переменную использовать
Какую переменную, в каком присваивании?
>SELECT @@IDENTITY
что такое @@IDENTITY?
← →
sniknik © (2007-11-11 10:14) [3]> Какую переменную, в каком присваивании?
в этом
> но как я буду присваивать эти адреса новой организации, если я не знаю её ключа.
вот где ты не знаеш что присваивать, но чтото присваиваеш, там и ставь @@IDENTITY.
> что такое @@IDENTITY?
F1 в нужном месте полностью ответит на твой вопрос.
← →
boalse © (2007-11-11 11:10) [4]PARAMETERS POrgName Text ( 225 );
INSERT INTO Org ( NAME )
VALUES (POrgName)
SELECT @@IDENTITY
Так чтоли? В акцесе не работает, пишет ошибка синтексиса, мол после VALUES (POrgName) должна стоять точка с запятой и дальше инструкций быть не должно. Пример посмотрел в хелпе для SQL Server 2000.
Пробовал вызывать SELECT @@IDENTITY отдельным запросом сразу после добавления, возвращает всегда 0.
← →
Palladin © (2007-11-11 11:12) [5]значит у тебя нет первичного ключа и/или его тип не "Счетчик"
← →
Palladin © (2007-11-11 11:17) [6]зачем вообще 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;
← →
sniknik © (2007-11-11 11:20) [7]> значит у тебя нет первичного ключа и/или его тип не "Счетчик"
не, не изза этого, тут ему правильно в проигнорированной ошибке вернуло -"дальше инструкций быть не должно.", в аксессе все "однозапросно" (даже "процедуры").
> Пробовал вызывать SELECT @@IDENTITY отдельным запросом сразу после добавления, возвращает всегда 0.
ошибка в 17й строке.
← →
sniknik © (2007-11-11 11:22) [8]> зачем вообще PARAMETERS? почему бы так не вставлять?
одна из форм синтаксиса в accecc. очень "любима" мастером запросов в самом аксессе.
← →
Palladin © (2007-11-11 11:23) [9]
> sniknik © (11.11.07 11:20) [7]
да это я про то, что ему ноль возвращается на идентити...
ошибка то про инструкции понятна :)
← →
sniknik © (2007-11-11 11:26) [10]> что ему ноль возвращается на идентити...
ноль это от того, что запрос на вставку и получение в разных контентах, например с разными "конекшионами", или с переконектом между этими запросами, или... в общем в 17й строке.
← →
sniknik © (2007-11-11 11:33) [11]sniknik © (11.11.07 11:26) [10]
+
т.е. на каждое подключение Jet создает свой экземпляр COM обьекта. естественно все значения переменных одного экземпляра, не видны в другом (имеют другие значения).
тут неизвестна причина (17), т.к. вариантов довольно много, но ясно, что 0 читается из другого экземпляра обьекта, не того где делается инсерт.
← →
boalse © (2007-11-11 11:35) [12]Palladin, спасибо, это подходит. Но вопрос возник. q.ExecSQL и q.Open, это всё в одной транзакции происходит? То есть не получится ли так, что сначало один пользователь вызывал q.ExecSQL и добавилась новая запись, потом почти одновременно другой пользователь тоже вызвал q.ExecSQL и добавил ещё одну запись, ну и наконец первый юзер вызывает q.Open и что он получает, случайно не идентификатор на новую запись второго пользователя? Такая ситуация возможна, или я глупость сказал?
← →
boalse © (2007-11-11 11:37) [13]тут неизвестна причина (17), т.к. вариантов довольно много, но ясно, что 0 читается из другого экземпляра обьекта, не того где делается инсерт.
а, тоесть Identity она только в контексте экземпляра отдельного работает. Тогда похоже точно глупость ляпнул в предыдущем :)
← →
Palladin © (2007-11-11 11:46) [14]
> 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
:)
← →
Palladin © (2007-11-11 11:47) [15]учитывая, что без назначенного Connection, но назначенного ConnectionString TADOQuery будет создавать свой собстенный экземпляр TADOConnection
← →
boalse © (2007-11-11 11:56) [16]Если назначать не ConnectionString, а Connection, получается та ситуёвина, про которую я говорил.
Palladin, спасибо большое, я прозрел :)
← →
Anatoly Podgoretsky © (2007-11-11 12:39) [17]При работе с IDENTITY всегда надо думать об области ее действия.
Например в первом приближение это соединение, далее пакет.
В MS SQL надо что бы запрос на вставку и запрос на получение ИД должен быть в одном пакете. Для Акцесс возможно достаточно, что бы было одно соединение. Легко проверяется.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.043 c