Привет всем!
Использую C5/XP + MSSQL2000
На сервере есть таблица, в ней поле ID с признаком Identity.
добавляю новую запись, ID генерится как положено.
А как мне непосредственно после добавления узнать это самое значение ID, которое сервер сгенерировал?
Написал: PL(12)
Как получить ID непосредственно после добавления записи?
Модератор: Andrew™
Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
select @@IDENTITY
--
baa@dionis.ru
Например,
С уважением, Михаил
Вот как раз IDENT_CURRENT использовать не надо, иначе в
многопользовательском режиме будут грабли. Совсем недавно я постил
письмо с примером:
В Кларионе:
Павел Яковенко
Привет, Павел. А как насчет вырезки из 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 вернёт автоинкремент, сгенерённый в
любой таблице?
С уважением, Михаил
(Добавление)
Здравствуйте, Pavel.
Эт какие такие грабли могут быть, если получить в этой же транзакции
IDENT_CURRENT?
А вот с @@IDENTITY можешь получить грабли, если у твоей таблицы есть
триггер на INSERT и в нем идет добавление еще в другие таблицы...
--
С уважением,
Олег mailto:clarion@hotbox.ru
Написал: ClaList(2)
--
baa@dionis.ru
Например,
Код: Выделить всё
queryfile FILE,DRIVER(MSSQL),PRE(QF)
RECORD RECORD,PRE()
Query CSTRING(1024)
END
END
!============
queryfile{prop:sql}='SELECT IDENT_CURRENT('''&queryfile{PROP:Name}&''')'
next(queryfile)
myfile.Id=QF:Query
Вот как раз IDENT_CURRENT использовать не надо, иначе в
многопользовательском режиме будут грабли. Совсем недавно я постил
письмо с примером:
Код: Выделить всё
CREATE TABLE IdentityTest (
Id Int IDENTITY ( 1, 1) NOT NULL ,
Name char( 100) NOT NULL
)
Код: Выделить всё
IF NOT Access:IdentityTest.Insert()
IdentityTest{prop:sql} = 'SELECT @@IDENTITY'
Next(IdentityTest)
IF NULL(IDE:Id)
message('Разрыв соединения')
ELSE
message('Сервер присвоил IDENTITY = '&IDE:Id)
END
END
Привет, Павел. А как насчет вырезки из 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 вернёт автоинкремент, сгенерённый в
любой таблице?
С уважением, Михаил
(Добавление)
Здравствуйте, Pavel.
Ну допрограммировались...PNY> Вот как раз IDENT_CURRENT использовать не надо, иначе в
PNY> многопользовательском режиме будут грабли. Совсем недавно я постил
PNY> письмо с примером:
Эт какие такие грабли могут быть, если получить в этой же транзакции
IDENT_CURRENT?
А вот с @@IDENTITY можешь получить грабли, если у твоей таблицы есть
триггер на INSERT и в нем идет добавление еще в другие таблицы...
--
С уважением,
Олег mailto:clarion@hotbox.ru
Написал: ClaList(2)
Привет, Павел. А как насчет вырезки из MS Books Online:Все так и есть. Просто если есть уверенность, что другая сессия не
вмешается между добавления и выборкой, то IDENTITY_CURRENT подойдет. А
@@IDENTITY действительно вернет значение, сгенерированное для любой
таблицы. И как тут правильно заметили, если на операцию добавления стоит
триггер, который добавляет записи в другую таблицу с автоинкрементом, то
тоже будет косяк. В такой ситуации поможет SCOPE_IDENTITY, но у меня в
Кларионе он всегда возвращает NULL. Так что, в принципе, косяк возможен
в любом варианте.
@@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
DirectODBC, завернуть в одну транзакцию добавление записи на сиквел и
извлечение ID. Однако мало кто из кларионщиков может себе позволить
набивать код приложения сугубо вручную. Я лично сторонник шаблонного
подхода. И Слава Богу, наработанный годами шаблонный инструментарий (ШВС
в том числе) плюс кларионовские SQL Accelerator драйверы позволяют
строить приложения на базе сиквела практически так же уверенно, как и на
TPS.
С уважением,
---
Oleg Fomin
(Добавление)
Просто тебя можно было понять так, что IDENTITY это мега рулез и кроме негоСтоять. При чем тут поиск? Мы говорим про добавление записи. Поиск ...
больше ничего не надо. И если мы его не юзаем, то это суперотстой )
А он когда нибудь бывает по IDENTITY (доступ в справочник и извлечение... совсем другая вещь и далеко не всегда бывает по ключу.
потомков не в счет)?
Я не говорил, что это самое эффективное решение. Я всего лишь сказал, чтоТ.е. вместо того, чтобы прочитать одно поле типа INT я потяну весь
RECORD?
задача решается базовыми кларионовскими методами. И я никак не мог подумать,
что сервак перенапряжется, если ему ОДИН ЕДИНСТВЕННЫЙ ЛИШНИЙ РАЗ В ЖИЗНИ
придется придется достать не INT, а всю запись.
WBR, Nick Tsigouro
Написал: ClaList(2)