Как получить ID непосредственно после добавления записи?

ODBC

Модератор: Andrew™

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Гость

Сообщение Гость »

Привет всем!

Использую C5/XP + MSSQL2000

На сервере есть таблица, в ней поле ID с признаком Identity.
добавляю новую запись, ID генерится как положено.
А как мне непосредственно после добавления узнать это самое значение ID, которое сервер сгенерировал?
Написал: PL(12)
Гость

Сообщение Гость »

select @@IDENTITY

--
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)
Гость

Сообщение Гость »

Все так и есть. Просто если есть уверенность, что другая сессия не
вмешается между добавления и выборкой, то 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)
Ответить