Получение значения генератора в MS Access

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

hayova
Сообщения: 8
Зарегистрирован: 08 авг 2005, 21:03

Получение значения генератора в MS Access

Сообщение hayova » 08 авг 2005, 21:10

Подскажите пожалуйста, возможно ли каким-нибудь образом получить значение генератора в MS Access? А лучше даже не значение генератора, а то его значение, которое было дано в качестве ID только что созданной записи.
Заранее благодарю за помощь.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 08 авг 2005, 21:38


hayova
Сообщения: 8
Зарегистрирован: 08 авг 2005, 21:03

Сообщение hayova » 08 авг 2005, 21:43

Да читал я это...
Нет там ничего про то, как сделать сие действие в Access :(
SELECT GEN_ID(NEWCLIENT, 0) FROM RDB$DATABASE ничего не дает, так как запрос-то идет не к серверу :(

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 08 авг 2005, 22:39

во-первых, для указанной цели так делать НЕЛЬЗЯ. это ясно написано в статье. во-вторых, зтот запрос от любого другого ничем не отличается. и например через ODBC даже в Excel прекрасно выполняется.

SAMZ
Сообщения: 128
Зарегистрирован: 21 мар 2005, 08:17

Сообщение SAMZ » 09 авг 2005, 06:57

hayova писал(а):Да читал я это...
Нет там ничего про то, как сделать сие действие в Access :(
SELECT GEN_ID(NEWCLIENT, 0) FROM RDB$DATABASE ничего не дает, так как запрос-то идет не к серверу :(
Если я правильно тебя понял, то можно, напремер, так
Если у тебя есть генератор
MyGenerator
то достаточно написать, напрмер ХП

CREATE PROCEDURE GETID_FORTABLE RETURNS (
ID INTEGER)
AS
BEGIN
Id = GEN_ID(myGenerator, 1);
SUSPEND;
end

Вызов этой процедуры
select Id from GETID_FORTABLE
выдаст новое значение ключа.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 09 авг 2005, 10:17

процедура не нужна. вопрос в том, почему это запрос "идет не к серверу".

SAMZ
Сообщения: 128
Зарегистрирован: 21 мар 2005, 08:17

Сообщение SAMZ » 09 авг 2005, 10:33

kdv писал(а):процедура не нужна. вопрос в том, почему это запрос "идет не к серверу".
Я неправильно понял вопроса в первоначальной постановке. Человеку нужен индекс, который генератор присвоил некоторому полю. Но для этого просто надо брать значение из генератора и присваивать его этому полю явно перед постированием.
Не понял Вашей фразы "запрос "идет не к серверу". А куда он собственно идет

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 09 авг 2005, 10:36

может, не будем обсуждать, что он там имел в виду? см. третье сообщение, внимательно. :)

меня вообще удивляет, как так можно "читать", чтобы все делать наперекосяк, то есть, наоборот тому как написано в статье.

hayova
Сообщения: 8
Зарегистрирован: 08 авг 2005, 21:03

Сообщение hayova » 09 авг 2005, 13:34

Поясняю еще раз:
Статью я прочитал внимательно. А по сему: ID у меня присваивает записи сервер. Мне нужно узнать из Access'а какой собственно номер он этой новой записи присвоил.
Не к серверу, потому что при попытке например сдалать так:
select Id from GETID_FORTABLE
или так:
SELECT GEN_ID(NEWCLIENT, 0) FROM RDB$DATABASE
Акцес ругает на то, что нет такой таблицы (GETID_FORTABLE или RDB$DATABASE) и все в этом роде. Он "видит" только прилинкованные таблицы, содержащие данные.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 09 авг 2005, 14:01

Статью я прочитал внимательно. А по сему: ID у меня присваивает записи сервер. Мне нужно узнать из Access'а какой собственно номер он этой новой записи присвоил.
ох уж эти "внимательные" читатели. В статье как раз написано, что присвоил-то сервер, а когда ты начнешь получать gen_id(gen, 0), то ты получишь самое последнее выданное на текущий момент, а НЕ ТО, которое сервер вставил. Объясняю.

генератор x = 1
insert ... gen_id(x, 1) - в запись попало 2
insert ... gen_id(x, 1) - в запись попало 3

select gen_id(x, 0) - выдаст 3.

НО! Эти 2 инсерта могут быть как в одном приложении, так и выполнены ДВУМЯ разными пользователями. Кто быстрее, тот и успел. Твой инсерт может быть на самом деле первым - то есть вставится-то 2, а получишь ты по gen_id(x, 0) значение 3 !!!

Поэтому узнать, какое значение присвоил записи сервер, невозможно В ПРИНЦИПЕ. Почему в статье и написано, что надо сначала ПОЛУЧИТЬ новое значение, а потом ЗАПИСАТЬ его на сервер.

В статье то же самое чуть другими словами написано в разделе "Получение текущего значения генераторов", КРАСНЫМИ БУКВАМИ.
Акцес ругает на то, что нет такой таблицы (GETID_FORTABLE или RDB$DATABASE) и все в этом роде
ему таблицу rdb$database никто не запрещает видеть. кто ругается, как ругается? Почему Access ругается, а вот прямо сейчас Excel на этот же запрос НЕ ругается, и все корректно выдает?
Access должен этот запрос ОТПРАВИТЬ НА СЕРВЕР. Он не должен перекурочивать его и пытаться выполнить его своим локальным движком. Если такое происходит, значит это должно быть в настройках Access. Никакое другое офисное приложение MS так не делает. Оно честно шлет запрос на сервер и получает результат.

hayova
Сообщения: 8
Зарегистрирован: 08 авг 2005, 21:03

Сообщение hayova » 09 авг 2005, 15:01

Уважаемый kdv, я все понимаю про ГенИД, и уж тем белее не собирался его получать gen_id(gen, 0).
Вопрос как раз в том и состоял, что раз gen_id(gen, 0) носит чисто информативный характер, Max(ID)+1 тоже нельзя, и получить ID, сгенерированный только что сервером тоже нельзя, то вот как раз вопрос в том и состоит, КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 09 авг 2005, 15:16

hayova писал(а):Уважаемый kdv, я все понимаю про ГенИД, и уж тем белее не собирался его получать gen_id(gen, 0).
Вопрос как раз в том и состоял, что раз gen_id(gen, 0) носит чисто информативный характер, Max(ID)+1 тоже нельзя, и получить ID, сгенерированный только что сервером тоже нельзя, то вот как раз вопрос в том и состоит, КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
Если указанную статью действительно прочитал, а не просмотрел по диагонали, и этот вопрос остался - это клиника.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 09 авг 2005, 15:23

не стыкуется вот это:
Уважаемый kdv, я все понимаю про ГенИД,
и это
КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
лично мне непонятно, как можно утверждать что все понял, и тут же задавать такие вопросы. Ладно, я уже второй день добрый. Цитирую себя же:
www.ibase.ru/devinfo/generator.htm

"специальный объект базы данных, который генерирует уникальные последовательные числа"

"...гарантируется, что каждому пользователю будет всегда возвращено уникальное значение генератора.."
"В результате при создании новой записи полю CLIENT_ID будет автоматически присваиваться новое значение"

"Поскольку SQL-сервер не может сообщить клиентскому приложению о новом значении ключевого поля, необходимо сначала запросить уникальное значение с сервера, и только затем использовать его во вставляемой записи."

ПЕРЕВОЖУ:

Генераторы используются для суррогатных ключей, то есть для выдачи уникальных абстрактных номеров записям. Есть два способа помещения такого уникального номера в запись:
1. в триггере. Этот способ подходит, когда надо вставить запись, и все. То есть, главное - обеспечить уникальность идентификатора, т.к. нам пофиг, какое значение он получает.
2. получить на клиента новое значение (gen_id(x, 1)). Вставить его в запись. Здесь тоже "пофиг" значение, т.к. оно абстрактное, но его надо "показать" клиенту или приложению.

Я согласен, что статью про генераторы надо немножко переписать. Чтобы "и даже карапуз" понял. Но вообще-то, предполагается что человек, который ее читает, понимает механизмы клиент-сервера, то есть, как сервер общается с клиентом.

Lokki
Сообщения: 5
Зарегистрирован: 04 авг 2005, 10:02

Сообщение Lokki » 10 авг 2005, 10:37

Если я правильно понял вопрос, необходимо получить идентификатор добавленной записи?

Я делаю так:
* Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию

Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Так?

ЗЫЖ мое приложение на C#, как это программируется в Access я не знаю.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 10 авг 2005, 10:42

Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию

Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
это понятно, только max(id) тут вообще не нужен. Неужели так трудно получить новый идентификатор, а потом его вставить в запись?

Lokki
Сообщения: 5
Зарегистрирован: 04 авг 2005, 10:02

Сообщение Lokki » 10 авг 2005, 10:47

Нет, не трудно.
Просто у меня с одной БД могут работать несколько программ написанных разными людьми, поэтому мне удобнее присваивать идентификаторы средствами БД, а не отдавать на откуп программерам.
Спокойнее как-то :)

SAMZ
Сообщения: 128
Зарегистрирован: 21 мар 2005, 08:17

Сообщение SAMZ » 10 авг 2005, 11:05

Lokki писал(а):Нет, не трудно.
Просто у меня с одной БД могут работать несколько программ написанных разными людьми, поэтому мне удобнее присваивать идентификаторы средствами БД, а не отдавать на откуп программерам.
Спокойнее как-то :)
Не очень понятно, какое спокойствие ты себе так обесеспечиваешь. Если с твоей БД работают неосторожные разработчики, то они и при твоей схеме могут понаделать все, что угодно. Схема работы с генераторами, предложенная в вышеприведенных ссылках и удобнее и надежнее. Просто необходимо корпоративное соглашение Ваших разработчиков ее использовать.

hayova
Сообщения: 8
Зарегистрирован: 08 авг 2005, 21:03

Сообщение hayova » 10 авг 2005, 11:42

Всем огромное спасибо - разобрался :)
Все оказалось очень просто :)
Вот примерно такую функцию для получения номера заварганил (может кому сгодится еще) :)
' создаем Workspace
Set ws = DBEngine.CreateWorkspace("", "", "", dbUseODBC)
' создаем соединение
Set cnn = ws.OpenConnection("cnn", , , СтрокаПодключения)
' создаем запрос
Set qdf = cnn.CreateQueryDef("", "SELECT GEN_ID(ИмяГенератора, 1) FROM RDB$DATABASE;")
И получаем номер :)
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
GetNewID = rst(0)

Потом этот номер уже и вставляю куда нужно :)

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 10 авг 2005, 12:09

Lokki писал(а):Если я правильно понял вопрос, необходимо получить идентификатор добавленной записи?

Я делаю так:
* Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию

Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Так?
Достаточно быстрая работа в таком ключе стоит дополнительного descending index-а по ID. Ладно, предположим, начиная с FB1.5 можно сделать PK на descending индексе. Но это всё равно затратнее и тормознее одного обращения к генератору до вставки. Никто не мешает оставить в триггере страховку if (New.ID Is Null) then New.ID=Gen_ID.

Pierre
Сообщения: 1
Зарегистрирован: 09 июл 2007, 11:16

Блоб

Сообщение Pierre » 09 июл 2007, 11:28

добрый день
Люди добрые скажите как получить картинка с блоб тип данных в эксель
использую для этих цель IBEXPERT Любое Блоб не экспортируется.
в базе есть картинки в поле блоб . они крайне важный для работе но их видет кроме как в ибэксперт не получается . хотелось бы всё экспортировать

Ответить