Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
A1 Сообщений: 96 Дата регистрации: 11.11.2005 |
Уважаемые помогите рассказав
Использую курсорадаптеры для подсоединения к SQL SErver-ским таблицам. Все просто замечательно, но чую что кое-что можно сделать лучше, а точнее сказать правальнее. Допустим на сервере есть таблица, поле ID которой автоинкриментное, при создании курсорадаптера указваю, что разрещаю изменения и ключом ставлю поле ID И теперь сам вопрос: в программе, когда пишу TABLEUPDATE, как можно автоматически получать поле ID, сгенерированное на сервере. Сейчас получаю так - делаю рефреш КА после чего перемещаюсь на максимальное значение ID. |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
MichaelD Сообщений: 7578 Дата регистрации: 14.05.2005 |
A1,
Цитата:см. @@IDENTITY, IDENT_CURRENT('table_name'), SCOPE_IDENTITY() SQL Book online Цитата:Здесь проблема в том, что неизвестно чей именно ID ты получишь... О-очень вероятно, что не этим клиентом добавленный при интенсивной работе на добавление... ------------------ С уважением, Михаил Дроздов, Пермь, Россия |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
Влад Колосов Сообщений: 22664 Откуда: Ростов-на-Дону Дата регистрации: 05.05.2005 |
При использовании VIEW надежнее всего отказаться от автоинкремента на сервере.
------------------ Совершенство - это не тогда, когда нельзя ничего прибавить, а тогда, когда нечего убавить. |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
Aleksey Tsingauz [MSFT] Автор Сообщений: 407 Дата регистрации: 15.06.2004 |
Здесь есть пример forum.foxclub.ru. Примеры я постил на UT:
|
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
Владимир Максимов Сообщений: 14097 Откуда: Москва Дата регистрации: 02.09.2000 |
Извиняюсь, что поднял старую тему, но тут на www.sql.ru на нескольких страницах пытаемся убедить товарища FoXXX, что способ поиска новой записи в Remote View как Requery()+Go Bottom - работает только при выполнении определенных условий. Ну, ладно, товарищь так отдыхает...
Но вообще-то, вопрос был поднят более общий. Все по той же теме. Как получить значение поля IDENTITY при работе через CAD. В связи с этим еще раз посмотрел решения предложенные Алексеем. Не ради критики, а для пояснения тем, кто пойдет тем же путем... Вкратце, их суть сводится к следующему 1) через ODBC - после успешного создания новой записи читается значение @@IDENTITY 2) через ADO - вместо прямой команды вставки формируется хранимая процедура, куда в качестве параметра передаются значения полей. В этой процедуре собственно и выполняется команда INSERT и возвращается значение SCOPE_IDENTITY() 3) AutoRefresh - в таблицу вводится поле или набор полей, по значению которого также можно однозначно идентифицировать запись. Это НЕ ключевые поля. После вставки записи осуществляется поиск новой записи по значению этих вспомогательных полей 4) это дубль способа 2) несколько по другому оформленный. Недостатки: 1) через ODBC - Работает, если у таблицы, куда происходит вставка нет триггера, в теле которого также есть вставка в таблицу имеющую поле типа IDENTITY. В этом случае получим значение поля из этой второй таблицы 2) и 4) через ADO - Вполне рабочее решение. Единственный недостаток - это избыточность (зачем посылать те поля, в которых ничего не ввели) и проблемы в случае, если в таблице допустимы поля со значением NULL (как отличить те поля в которые ничего не ввели от тех, в которые ввели пустое значение. Здесь подошло бы DEFAULT на поля, но как это настроить в CAD?) 3) AutoRefresh - Далеко не всегда в таблице есть дублирующие поля, которые могут взять на себя роль ID, даже в пределах выборки. |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
Aleksey Tsingauz [MSFT] Автор Сообщений: 407 Дата регистрации: 15.06.2004 |
Здравствуйте, Владимир!
Действительно вопрос достаточно серьезный и общие пояснения не помешают. Существут несколько разных способов извлечения значения IDENTITY после вставки новой записи на сервере и примеры демонстрируют как использовать эти способы с CursorAdapter-ом. 1) Запросить значение @@IDENTITY (как уже было отмечено, иногда этот способ использовать нельзя). Как с помощью CursorAdapter-а заставить TABLEUPDATE автоматически сохранять значение в поле локального курсора: - Вручную послать запрос на сервер и изменить значение поля в обработчике AfterInsert (Пример №1), работает для ODBC и ADO. - Вручную запросить значение поля из RecordSet-a и изменить значение поля в обработчике AfterInsert, работает только для ADO и только если CursorAdapter сконфигурирован для вставки новых записей через RecordSet. - Использовать хранимую процедуру для вставки и обновлять значение поля с помощью OUTPUT параметра (аналогично примерам №2 и №4), работает для ODBC и ADO. - Использовать InsertCmdRefreshFieldList без указания InsertCmdRefreshCmd (Пример ниже), работает только для ADO и только если CursorAdapter сконфигурирован для вставки новых записей через RecordSet. - Использовать InsertCmdRefreshFieldList вместе с InsertCmdRefreshCmd (Пример №3.1 и №3.2), работает для ODBC и ADO. 2) Запросить значение SCOPE_IDENTITY(). Как с помощью CursorAdapter-а заставить TABLEUPDATE автоматически сохранять значение в поле локального курсора: - Использовать хранимую процедуру для вставки и обновлять значение поля с помощью OUTPUT параметра (Пример №2 и №4), работает для ODBC и ADO. 3) Запросить значение из записи используя альтернативный уникальный ключ записи. Как с помощью CursorAdapter-а заставить TABLEUPDATE автоматически сохранять значение в поле локального курсора: - Вручную послать запрос на сервер и изменить значение поля в обработчике AfterInsert, работает для ODBC и ADO. - Использовать хранимую процедуру для вставки и обновлять значение поля с помощью OUTPUT параметра, работает для ODBC и ADO. - Использовать InsertCmdRefreshFieldList вместе с InsertCmdRefreshKeyFieldList (Пример №3.3), работает для ODBC и ADO. - Использовать InsertCmdRefreshFieldList вместе с InsertCmdRefreshCmd, работает для ODBC и ADO. Как раз таки ЭТО КЛЮЧЕВЫЕ поля. Часто таблица имеет несколько уникальных ключей, надо просто не проглядеть это во время дизайна и создать соответствующие CONSTRAINTS. Если рассматривать таблицу с IDENTITY, то не всегда, но очень, очень часто таблица имеет альтернативный уникальный ключ. Почему? Потому что, как правило, IDENTITY поле - это служебное поле, используемое для создания связей между таблицами и не несущее никакой смысловой нагрузки. С точки зрения дизайна таблицы, можно считать, что это поле добавляется в уже готовую таблицу, которая по законам дизайна уже должна иметь уникальный ключ. После добавления IDENTITY, тот ключ никуда не исчезает, просто его "забывают", что делать очень вредно, хотя бы исходя из соображений поддержания целостности и непротиворечивости базы. Простой пример: Для таблицы Categories в Northwind создан всего один уникальный ключ по CategoryId - явный баг в дизайне. Должен быть еще уникальный ключ по CategoryName. Разве имеет смысл иметь две разные категории с одним и тем же именем? Как пользователь должен их различать, помнить номера? Проблему избыточности можно решить, анализируя GETFLDSTATE в BeforeInsert и меняя cInsertCmd параметр на вызов соответствующей процедуры. Но, по-моему, проще передавать значения для всех полей вместе с GETFLDSTATE(-1) и анализировать GETFLDSTATE(-1) уже в процедуре. Это так же позволит корректно обрабатывать незаданные поля. А чтобы зря не гонять большие объемы данных для неизмененных полей, можно передавать для них NULL. Что-то типа:
Алексей. Обещанный пример:
Исправлено 1 раз(а). Последнее : Aleksey Tsingauz [MSFT], 20.03.06 08:17 |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
WiRuc Сообщений: 1012 Дата регистрации: 09.04.2002 |
Небольшое уточнение.
Настройка ANSI_NULLS запоминается при создании ХП, так что строка SET ANSI_NULLS OFF просто игнорируется. Надо было сначала выдать SET ANSI_NULLS OFF через SQLEXEC, а затем создавать процедуру. А по сути вопроса, считаю, что метод 2 (через ХП) является единственно правильным. |
Re: Как автомат-ки получать автоинкриментное поле SQL сервера в КА | |
---|---|
Aleksey Tsingauz [MSFT] Автор Сообщений: 407 Дата регистрации: 15.06.2004 |
Поскольку вопрос продолжает быть актуальным, помещаю еще один способ извлечения IDENTITY CursrAdapter-ом с помощью SCOPE_IDENTITY(). Этот способ основан на использовании вспомогательной временной хранимой процедуры и на использовании события CursorAdapter.BeforeInsert, которое добавляет вызов процедуры в конец команды INSERT (будь то автоматически сгенерированная команда или команда явно заданная через CursorAdapter.InsertCmd). Код процедуры и события BeforeInsert абсолютно не зависят от схемы таблицы, единственное что требуется знать - имя столбца в курсоре куда сохранить значение. Думаю, что самые придирчевые критики будут удовлетворены этим подходом, можно написать один базовый класс и использовать его для любой таблицы с IDENTITY.
Пример для ODBC, но способ также должен работать для ADO:
Алексей. |
© 2000-2024 Fox Club  |