Конференция "Базы" » получить Insert Id после запроса INSERT... [D7, MSAccess via Ado]
 
  • 123456711 (18.07.08 13:40) [0]
    ... у базы Standart Jet DB (Access) через Ado.

    Другими словами вставляю строку в таблицу у которой поле [id] - счетчик. Как получить значение этого счетчика после вставки?

    Интересует все, кроме метода Select max([id]) FROM [SomeTable].
  • Сергей М. © (18.07.08 13:56) [1]
    А другие уникальные ключи у этой таблицы имеются ?
    Допускается ли модификация структуры таблицы для решения задачи ?
    Допускается ли одновременная работа с таблицей в контексте более чем одной транзакции одновременнно ?
  • Palladin © (18.07.08 13:56) [2]
    select @@Identity
  • stas © (18.07.08 14:02) [3]
    Palladin ©   (18.07.08 13:56) [2]
    Это Access
  • sniknik © (18.07.08 14:09) [4]
    > Это Access
    да, это все меняет... тогда надо
    select @@Identity

  • 123456711 (18.07.08 14:16) [5]

    > Palladin ©   (18.07.08 13:56) [2]
    >
    > select @@Identity
    >

    Спасибо! Как раз то, что нужно!
  • stas © (18.07.08 14:24) [6]
    Palladin ©   (18.07.08 13:56) [2]
    Работает! незнал.
    sniknik ©   (18.07.08 14:09) [4]
    ага :)
  • Anatoly Podgoretsky © (18.07.08 15:54) [7]
    stas ©   (18.07.08 14:02) [3]
    Ты укоряешь или хвастуешься незнанием?
  • MsGuns © (18.07.08 16:15) [8]
    Указанный селест должен следовать непосредственно после запроса на вставку в одном и том же TADOCommand, и считывать его через _RecordSet, полученный от него:

    var
     cm: TADOCommand;
     ds: TADOQuery;
    ..

    cm := TADOCommand.Create(nil);
    cm.Connecton := ..
    cm.CommandText := 'Insert ...   '+' Select @@indentity';
    ds := TADOQuery.Create(nil);
    ds.recordset := cm.execute;
    NewID :=  ds.recordset.Fields[0].AsInteger;
    ds.Free;
    cm.Free;

    Try .. finally/except сами поставите ;)
  • stas © (18.07.08 16:16) [9]
    Anatoly Podgoretsky ©   (18.07.08 15:54) [7]
    stas ©   (18.07.08 14:24) [6]
  • sniknik © (18.07.08 16:30) [10]
    > Указанный селест должен следовать непосредственно после запроса на вставку в одном и том же TADOCommand, и считывать его через _RecordSet,
    > полученный от него:
    вовсе не обязательно мудрить с TADOCommand и _RecordSet -ом.
    что действительно нужно так это общий конект (TADOConnection) у обоих (TADOCommand, TADODataSet) и синхронное выполнение запросов (что по умолчанию), ну и считывать сразу после вставки само собой.
  • ANB (18.07.08 16:42) [11]

    > sniknik ©   (18.07.08 16:30) [10]

    В мс скл не поможет. Там только в одной команде должно идти.

    В аксесс - не знаю.
  • MsGuns © (18.07.08 16:47) [12]
    >sniknik ©   (18.07.08 16:30) [10]
    >вовсе не обязательно мудрить с TADOCommand и _RecordSet -ом.

    Не вижу ничего мудреного. В конце концнв можно написать универсальную функцию и подключить ее к делфе.

    >что действительно нужно так это общий конект (TADOConnection) у обоих (TADOCommand, >TADODataSet) и синхронное выполнение запросов (что по умолчанию), ну и считывать сразу >после вставки само собой.

    Этого может быть недостаточно
  • sniknik © (18.07.08 16:54) [13]
    > В мс скл не поможет.
    а не про mssql разговор.

    > Этого может быть недостаточно
    достаточно с гарантией...
  • stas © (21.07.08 10:38) [14]
    ANB   (18.07.08 16:42) [11]
    в mssql если есть триггер на таблице на insert в другую таблицу, то и в одной команде непоможет, нужно функцию использовать.
  • Anatoly Podgoretsky © (21.07.08 11:06) [15]
    stas ©   (21.07.08 10:38) [14]
    Чукча не читатель!
    Сказали же, что про mssql речь не идет.
  • stas © (21.07.08 12:07) [16]
    Anatoly Podgoretsky ©   (21.07.08 11:06) [15]
    Да знаю я.
    Ну, раз уж затронули mssql....
  • Dmitry S © (22.07.08 15:02) [17]

    > Сказали же, что про mssql речь не идет.

    Сори за офтоп.
    Вот мне интересно, откуда берется множественное число в подобных фразах. Для преувеличения значимости сказанного? Или это попытка манипуляции с помощью общества?
  • Johnmen © (22.07.08 17:36) [18]

    > Dmitry S ©   (22.07.08 15:02) [17]

    В соответствии с нормами русского языка. Ничего более.
    Для тех, кто писатель, не читатель.
  • Нат (29.07.08 11:28) [19]
    Как упоминалось можно найти запись по другим ключам.
    Например,  если есть поле ДатаВремя создания записи - найти свой ИД по нему, но есть моменты со вставкой и поиском.
    Еще можно  Recynс-Requery + bookmark использовать.
    Но это все медленнее.
  • Ega23 © (29.07.08 11:52) [20]

    > Например,  если есть поле ДатаВремя создания записи - найти
    > свой ИД по нему


    Не получится.
  • Нат (29.07.08 18:56) [21]

    > Не получится.

    У меня получалось.  Но без изящества.
  • Ega23 © (30.07.08 10:01) [22]

    > У меня получалось.


    Это просто повезло. На равенство DateTime сверять - глупо, надо на больше-равно - меньше-равно. А так - высока вероятность того, что кто-то ещё кроме тебя успеет это захватить.
    В общем, не получится так.
  • Нат (30.07.08 10:38) [23]
    d := now(); ... insert ... select или look
    безо всяких больше либо...
    строго равно! до долей секунды
    и все получается.
  • Ega23 © (30.07.08 10:44) [24]

    > и все получается.


    Тебе просто повезло.
    1. Ты ещё, похоже, не натыкался на проблему с синхронизацией времени в сети.
    2. Ты ещё, похоже, не натыкался на проблему с переходом на зимнее время.
  • Anatoly Podgoretsky © (30.07.08 10:49) [25]
    Для подобных дурных подходов есть аппробированое решение - поиск сравнение по всем полям, реализовано в DB.VCL если не применять особых методов, условие не использовать никаких идентифицирующих полей, главное удалить ПК если он есть.
  • Нат (30.07.08 11:05) [26]
    Подход так себе, через голову.О чем сразу было сказано.
    Но работает.
    И везение не при чем. Пришлось морщить лоб.
    В том случае еще имелось поле Autor, поэтому захватить чужую запись с таким же временем (буде повезет) проблематично.
  • Anatoly Podgoretsky © (30.07.08 11:16) [27]

    > и все получается.

    Везет.
  • Anatoly Podgoretsky © (30.07.08 11:18) [28]

    > Ega23 ©   (30.07.08 10:44) [24]

    3. и не понимает устройства типа TDateTime
    4. и не понимает принципов работы с плавающей запятой
    5. и не понимает принципов работы SQL серверов, где (Fld = Value) <> Value
  • stas © (30.07.08 11:26) [29]
    >Нат
    Искать по времени свой ID это глупости
    1. Быстрее будет уже (Select Max(ID) from mytable).
    2. поле датавремя точность до милисекунд, а знаешь сколько транзакций может пройти в одну милисекунду?
    3. и зачем изобретать что-то если есть стандартные средства определения ID.
  • Нат (30.07.08 11:28) [30]
    Я здесь.
    Скажите ты, иначе это грубость, профессор.

    Я чего не понимаю, стараюсь учиться.
  • Ega23 © (30.07.08 11:30) [31]

    > 1. Быстрее будет уже (Select Max(ID) from mytable).


    Да нельзя так делать, ёлы-палы!!!
    Ну где гарантия того, что это - именно твоя вставка, а не соседнего клиента, который выполнял вставку сразу за тобой??
  • stas © (30.07.08 11:38) [32]
    Ega23 ©   (30.07.08 11:30) [31]

    Конечно нельзя, но если уж выбирать по дате или (Select Max(ID) from mytable), то лучше последнее.
  • Нат (30.07.08 11:47) [33]
    Может и глупость, что было-то было... и работало.
    Как заметил Ega23,  (Select Max(ID) from mytable) еще менее надежный вариант.
    Хотя он гораздо изящнее варианта с датой. Там нужно изголяться в силу

    > устройства типа TDateTime

    К слову, он был заменен на ... что Вы думаете?
    id:=ExecSQL ('Select max([id])+1 FROM [SomeTable]')
    TDataSet. Insert(id)
    если ошибка - то заново.
    И кажется, на так и жило.

    Просто был задан вопрос

    > Интересует все, кроме метода Select max([id]) FROM [SomeTable].
  • stas © (30.07.08 11:51) [34]
    Нат   (30.07.08 11:47) [33]
    Так это уже вы автоинкримент выдумываете, а вопрос был как определить значение автоинкремента после вставки.
  • Ega23 © (30.07.08 11:56) [35]
    Тогда уж давай будем последовательным:
    Select IsNull(max([id])+1, 1) FROM [SomeTable]

  • Нат (30.07.08 12:26) [36]

    > пределить значение автоинкремента после вставки

    Совсем чуть-чуть отклонились.

    Ega23
    IsNull(max([id])+1, 1) это лучше, но имелось в виду другое.
    Принципиальное отличие - вставка не запросом, а DataSet.Insert ...
    Т.е. определяем ДО вставки, вставляем и остаемся на нужной записи.
    И никаких поисков уже не надо.
  • Ega23 © (30.07.08 12:39) [37]

    > Т.е. определяем ДО вставки, вставляем и остаемся на нужной
    > записи.


    Я понял, что имелось ввиду. Но один фиг, это всё надо одним скриптом делать.
    Я Max+1 выберу, а вставку данных в грид ещё не закончу.
    В это время Max+1 выберет Вася Пупкин (а значение - то же самое, я ещё данные не закомиттил), быстрее меня забьёт данные, сделает коммит, и я получу insert error.
  • Нат (30.07.08 12:56) [38]
    Точно. Тогда и все на повтор.

    > TDataSet. Insert(id)если ошибка - то заново.

    А просто запросом - вообще без гарантии от Васи. Залеты были чаще, чем с датой.
    Сложно придумать лучше, чем:

    > да, это все меняет... тогда надо select @@Identity

    Разве что прямо на серверной стороне... ну там свои штуки.
  • stas © (30.07.08 13:14) [39]
    есть @@Identity, чего еще заморачиваться?
  • Anatoly Podgoretsky © (30.07.08 13:30) [40]
    > stas  (30.07.2008 11:51:34)  [34]

    А там он определен, если ты не заметил.
  • Anatoly Podgoretsky © (30.07.08 13:32) [41]
    > Нат  (30.07.2008 12:26:36)  [36]

    А нафига Insert - ты думаешь факт определения ИД изменится, если делать вставку с помощью запроса.
  • Anatoly Podgoretsky © (30.07.08 13:33) [42]

    > Разве что прямо на серверной стороне... ну там свои штуки.

    Где ты нашел серверную сторону в Акцесс?
  • Anatoly Podgoretsky © (30.07.08 13:34) [43]
    Кстати а вас не очень занесло с триггерами в Акцесс?
  • Нат (30.07.08 13:40) [44]
    Серверный курсор имеет место быть, однако с закладки пожелали счастливо оставаться.
    Без закладко грид ничего не смог отобразить.
    На этом и расстались.
    С серверной стороной в Акцессе.
  • stas © (30.07.08 13:56) [45]
    Anatoly Podgoretsky ©   (30.07.08 13:30) [40]
    где там?
    Anatoly Podgoretsky ©   (30.07.08 13:30) [40]-[43]
    Разошелся...
  • Anatoly Podgoretsky © (30.07.08 14:48) [46]
    > stas  (30.07.2008 13:56:45)  [45]

    Читай все обсуждение.
  • Игорь Шевченко © (30.07.08 14:55) [47]
    Надо использовать RETURNING. Это правда тоже не в Access-е, но какая нахрен разница ?
  • Sergey13 © (30.07.08 15:10) [48]
    > [47] Игорь Шевченко ©   (30.07.08 14:55)

    Надо НЕ использовать Access, тогда заработает RETURNING. 8-)
  • Игорь Шевченко © (30.07.08 15:15) [49]
    Sergey13 ©   (30.07.08 15:10) [48]

    > Надо НЕ использовать Access, тогда заработает RETURNING


    Абсолютно верно - Oracle XE наше все :) К тому же там есть средство миграции из Access-а, если мне память не изменяет
  • Ega23 © (30.07.08 15:27) [50]

    > Oracle XE наше все :)


    Ацтой Оракл, ini-файлы рулят.
  • Игорь Шевченко © (30.07.08 15:40) [51]
    Ega23 ©   (30.07.08 15:27) [50]

    "Старайтесь избегать «оффтопиков». Добавляя свое сообщение, убедитесь, что оно соответствует обсуждаемой теме"
    http://www.delphimaster.ru/forums.shtml#rule
  • Нат (31.07.08 03:15) [52]
    MsGuns

    > cm.CommandText := 'Insert ...   '+' Select @@indentity';

    А как тебе удалось загнать обе команды в один запрос?
    И на какой версии Акцесса?
  • Ega23 © (31.07.08 10:40) [53]

    > А как тебе удалось загнать обе команды в один запрос?


    А в чём проблема?


    ADODataSet1.CommandText := 'Set NoCount ON;
    Insert into xxx (aName) Values ('
    111');
    Insert into xxx (aName) Values ('
    222');
    Insert into xxx (aName) Values ('
    333');
    Insert into xxx (aName) Values ('
    444');
    Insert into xxx (aName) Values ('
    555');
    Insert into xxx (aName) Values ('
    666');
    Set NoCount OFF;

    Select * from xxx'
    ;

    ADODataSet1.Open;

  • Anatoly Podgoretsky © (31.07.08 11:14) [54]
    > Ega23  (31.07.2008 10:40:53)  [53]

    Акцесс требует точки с запятой между частями?
  • Ega23 © (31.07.08 11:19) [55]

    > Акцесс требует точки с запятой между частями?


    Ну это не для Access, это TSQL. А точка с запятой - это уже просто тупо привычка. Многие СУБД требуют. TSQL не требует, но ставить можно.
  • Anatoly Podgoretsky © (31.07.08 13:44) [56]
    Ну вообще то тема по Акцесс.
    Ладно не знаешь, но не так это и важно. Когда будет важно, то проверка займет несколько секунд.
  • Нат (31.07.08 18:09) [57]
    В акцессе можно ставить точку с запятой после запроса, однако акцесс не терпит после  больше ничего, т.к. считает ";" завершением инструкции.
    Не прокатывает такая конструкция.

    Вобчем и без запятой тож не хочет.
    Ток по-отдельности.
  • Anatoly Podgoretsky © (01.08.08 09:43) [58]
    Ну так в Акцесс, что по отдельности, что вместе результат одинаков - это же файлсерверная БД

    По идеологии SQL как было задумано голубым гигантом и как позволяла тогда техника (телетайпы) надо было как то завершать инструкцию, что бы ее можно было выполнить, для этой цели была выбрана точка с запятой.

    При программном решение это нонсенс, если только не рассматривать это как набор независимых инструкций, но система поддержки должна поддерживать это.

    А вот конструкция, для T-SQL или подобных

    инструкция1
    ...
    инструкция N



    Это одна инструкция и естественно она выполняется как единое целое, на этом кстати основан и SQL Ejection

    Не уверен, что это было хорошей идеей.
 
Конференция "Базы" » получить Insert Id после запроса INSERT... [D7, MSAccess via Ado]
Есть новые Нет новых   [134435   +35][b:0][p:0.002]