Все так и есть. Просто если есть уверенность, что другая сессия не
вмешается между добавления и выборкой, то IDENTITY_CURRENT подойдет. А
@@IDENTITY действительно вернет значение, сгенерированное для любой
таблицы. И как тут правильно заметили, если на операцию добавления стоит
триггер, который добавляет записи в другую таблицу с автоинкрементом, то
тоже будет косяк. В такой ситуации поможет SCOPE_IDENTITY, но у меня в
Кларионе он всегда возвращает NULL. Так что, в принципе, косяк возможен
в любом варианте.
Привет, Павел. А как насчет вырезки из MS Books Online:
@@IDENTITY and SCOPE_IDENTITY will return the last identity value
generated in any table in the current session. However, SCOPE_IDENTITY returns the
value only within the current scope; @@IDENTITY is not limited to a specific scope.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.
=========
Я правильно понимаю, что @@IDENTITY вернёт автоинкремент, сгенерённый в
любой таблице?
С уважением,
Михаил
(Добавление)
Ну допрограммировались...
Еще и не такое бывает. А грабли могут быть если не поменять уровень
изоляции транзакций. READ COMMITTED, устанавливаемый по умолчанию в
MSSQL, не будет блокировать транзакцию добавления записей и
IDENT_CURRENT будет возвращать чужие значения. Если поставить, скажем,
SERIALIZABLE, то все должно кочегарить
Павел Яковенко
Здравствуйте, Pavel.
Вот потому Кларионовскими методами к скул базам и не пристаю:)))
вдогонку, там еще курсоры сервера Клара пользует, жудкая гадость эта
Ваша......
--
С уважением,
Олег mailto:clarion@hotbox.ru
(Добавление)
Вообще-то не вижу причин, почему это нельзя сделать чисто кларионовскими
средствами. В нормальной таблице д.б. кроме ида еще и осмысленный уникальный
ключ. Вот по нему GET-ом и достаем вновь созданную запись и извлекаем ид.
WBR, Nick Tsigouro. MailTo:Nick@arsis.ru
(Добавление)
Ну и зачем тогда вообще такой тип поля как IDENTITY, если все равно
потом лезть в таблицу по ключу? Весь кайф использования пропадает...
--
С уважением,
Олег
(Добавление)
Отнюдь. По этому ключу нужно слазить один раз в жизни. Сразу после создания
записи, чтобы вешать на нее потомков. А потом, скажи, когда тебе нужна
конкретная запись ты ее поиск по чему организуешь? По IDENTITY или по
чему-то более содержательному?
WBR, Nick Tsigouro
(Добавление)
Стоять. При чем тут поиск? Мы говорим про добавление записи. Поиск
совсем другая вещь и далеко не всегда бывает по ключу.
Вот по нему GET-ом и достаем вновь созданную запись и
извлекаем ид.
Т.е. вместо того, чтобы прочитать одно поле типа INT я потяну весь
RECORD?
--
С уважением,
Олег
(Добавление)
На сервере есть таблица, в ней поле ID с признаком Identity.
добавляю новую запись, ID генерится как положено.
А как мне непосредственно после добавления узнать это самое
значение ID, которое сервер сгенерировал?
Да, проблема актуальная, без этого ни встать на новую запись в бровсе по
возвращении из формы, ни детишек наплодить в форме. А кларионовская
автонумерация на сиквеле не катит.
Идея такая:
1) Сохраняем текущую запись в загодя заготовленном буфере;
2) Извлекаем 'SELECT max(ID) FROM TheTable' сразу после ADD(TheTable);
3) Извлекаем запись по найденному значению первичного ключа;
4) Сравниваем запись с сохраненным буфером;
5) Если вдруг находим расхождение,
тогда берем предыдущий ключ (TheTable.ID -= 1) и возвращаемся на
пункт 3;
Данное решение универсально и легко ложится на язык шаблонов. Как раз
сегодня именно этим и занимался, правда пункты 1, 4 и 5 не успел
воплотить в жизнь. Использую ШВС плюс ODBC библиотечку того же автора.
Код: Выделить всё
#EXTENSION(ODBCIdentitySupport,'ODBC Identity
Support'),PROCEDURE,REQ(SaveButton(Clarion),AFTER)
#PROMPT('Identity Table:',FILE),%IdentityTable
#PROMPT('Primary Key:',KEY(%IdentityTable)),%IdentityKey
#PROMPT('Identity Field:',COMPONENT(%IdentityKey)),%IdentityField
#!
#AT(%DataSectionBeforeWindow)
SQLSelectClass SQLSelectClassType
#ENDAT
#!
#AT(%BeforeWindowOpening)
SQLSelectClass.Init(GLOBAL:SQLConnectClass)
#ENDAT
#!
#AT(%InsideInsertRecord)
#FIX(%File,%IdentityTable)
#FIX(%Field,%IdentityField)
#IF(%FieldName)
#SET(%ValueConstruct,%FieldName)
#ELSE
#SET(%ValueConstruct,%FieldID)
#ENDIF
%IdentityField = SQLSelectClass.GetRequestResult('SELECT
max(%ValueConstruct) FROM %File')
GET(%IdentityTable,%IdentityKey)
#ENDAT
#!
#AT(%AfterWindowClosing)
SQLSelectClass.Kill
#ENDAT
P.S. Олегу Иванову:
Понимаю, оно конечно круто - использовать чисто
DirectODBC, завернуть в одну транзакцию добавление записи на сиквел и
извлечение ID. Однако мало кто из кларионщиков может себе позволить
набивать код приложения сугубо вручную. Я лично сторонник шаблонного
подхода. И Слава Богу, наработанный годами шаблонный инструментарий (ШВС
в том числе) плюс кларионовские SQL Accelerator драйверы позволяют
строить приложения на базе сиквела практически так же уверенно, как и на
TPS.
С уважением,
---
Oleg Fomin
(Добавление)
Стоять. При чем тут поиск? Мы говорим про добавление записи. Поиск ...
Просто тебя можно было понять так, что IDENTITY это мега рулез и кроме него
больше ничего не надо. И если мы его не юзаем, то это суперотстой

)
... совсем другая вещь и далеко не всегда бывает по ключу.
А он когда нибудь бывает по IDENTITY (доступ в справочник и извлечение
потомков не в счет)?
Т.е. вместо того, чтобы прочитать одно поле типа INT я потяну весь
RECORD?
Я не говорил, что это самое эффективное решение. Я всего лишь сказал, что
задача решается базовыми кларионовскими методами. И я никак не мог подумать,
что сервак перенапряжется, если ему ОДИН ЕДИНСТВЕННЫЙ ЛИШНИЙ РАЗ В ЖИЗНИ
придется придется достать не INT, а всю запись.
WBR,
Nick Tsigouro
Написал: ClaList(2)