Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.12.09;
Скачать: CL | DM;

Вниз

Получение сгенерированного акцессом ключа для новой записи   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.024 c
1-1189288423
Dr. Andrew
2007-09-09 01:53
2007.12.09
Чем можно заменить GetTickCount? Нужна точность до 1 мсек!


2-1194838802
d@nger
2007-11-12 06:40
2007.12.09
Jpeg и дата съемки


15-1194876600
Кирей
2007-11-12 17:10
2007.12.09
Подскажите, какой конструктор отчетов самый лучший для Delphi


2-1194868661
cosy
2007-11-12 14:57
2007.12.09
найдите ошибку пожалуста уже 2 часа на этот сорц смотрю


2-1194962162
Malik
2007-11-13 16:56
2007.12.09
ShellAPI парадокс и ничего более??