Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
3-1186049899
DmitrichJ
2007-08-02 14:18
2007.12.09
UpDate. Как изменить одну запись, если их несколько одинаковых?


2-1194804112
pirks
2007-11-11 21:01
2007.12.09
объединение RadioButton в группу...


15-1194451108
Max3m
2007-11-07 18:58
2007.12.09
PasswordChar +XP


15-1194548396
@!!ex
2007-11-08 21:59
2007.12.09
Закон и Linux


2-1195204511
Pro100
2007-11-16 12:15
2007.12.09
Дробная часть





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский