Получение значения генератора в MS Access
Модератор: kdv
Получение значения генератора в MS Access
Подскажите пожалуйста, возможно ли каким-нибудь образом получить значение генератора в MS Access? А лучше даже не значение генератора, а то его значение, которое было дано в качестве ID только что созданной записи.
Заранее благодарю за помощь.
Заранее благодарю за помощь.
Если я правильно тебя понял, то можно, напремер, так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 писал(а):процедура не нужна. вопрос в том, почему это запрос "идет не к серверу".
Не понял Вашей фразы "запрос "идет не к серверу". А куда он собственно идет
Поясняю еще раз:
Статью я прочитал внимательно. А по сему: ID у меня присваивает записи сервер. Мне нужно узнать из Access'а какой собственно номер он этой новой записи присвоил.
Не к серверу, потому что при попытке например сдалать так:
select Id from GETID_FORTABLE
или так:
SELECT GEN_ID(NEWCLIENT, 0) FROM RDB$DATABASE
Акцес ругает на то, что нет такой таблицы (GETID_FORTABLE или RDB$DATABASE) и все в этом роде. Он "видит" только прилинкованные таблицы, содержащие данные.
Статью я прочитал внимательно. А по сему: ID у меня присваивает записи сервер. Мне нужно узнать из Access'а какой собственно номер он этой новой записи присвоил.
Не к серверу, потому что при попытке например сдалать так:
select Id from GETID_FORTABLE
или так:
SELECT GEN_ID(NEWCLIENT, 0) FROM RDB$DATABASE
Акцес ругает на то, что нет такой таблицы (GETID_FORTABLE или RDB$DATABASE) и все в этом роде. Он "видит" только прилинкованные таблицы, содержащие данные.
ох уж эти "внимательные" читатели. В статье как раз написано, что присвоил-то сервер, а когда ты начнешь получать gen_id(gen, 0), то ты получишь самое последнее выданное на текущий момент, а НЕ ТО, которое сервер вставил. Объясняю.Статью я прочитал внимательно. А по сему: ID у меня присваивает записи сервер. Мне нужно узнать из Access'а какой собственно номер он этой новой записи присвоил.
генератор 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 !!!
Поэтому узнать, какое значение присвоил записи сервер, невозможно В ПРИНЦИПЕ. Почему в статье и написано, что надо сначала ПОЛУЧИТЬ новое значение, а потом ЗАПИСАТЬ его на сервер.
В статье то же самое чуть другими словами написано в разделе "Получение текущего значения генераторов", КРАСНЫМИ БУКВАМИ.
ему таблицу rdb$database никто не запрещает видеть. кто ругается, как ругается? Почему Access ругается, а вот прямо сейчас Excel на этот же запрос НЕ ругается, и все корректно выдает?Акцес ругает на то, что нет такой таблицы (GETID_FORTABLE или RDB$DATABASE) и все в этом роде
Access должен этот запрос ОТПРАВИТЬ НА СЕРВЕР. Он не должен перекурочивать его и пытаться выполнить его своим локальным движком. Если такое происходит, значит это должно быть в настройках Access. Никакое другое офисное приложение MS так не делает. Оно честно шлет запрос на сервер и получает результат.
Уважаемый kdv, я все понимаю про ГенИД, и уж тем белее не собирался его получать gen_id(gen, 0).
Вопрос как раз в том и состоял, что раз gen_id(gen, 0) носит чисто информативный характер, Max(ID)+1 тоже нельзя, и получить ID, сгенерированный только что сервером тоже нельзя, то вот как раз вопрос в том и состоит, КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
Вопрос как раз в том и состоял, что раз gen_id(gen, 0) носит чисто информативный характер, Max(ID)+1 тоже нельзя, и получить ID, сгенерированный только что сервером тоже нельзя, то вот как раз вопрос в том и состоит, КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
Если указанную статью действительно прочитал, а не просмотрел по диагонали, и этот вопрос остался - это клиника.hayova писал(а):Уважаемый kdv, я все понимаю про ГенИД, и уж тем белее не собирался его получать gen_id(gen, 0).
Вопрос как раз в том и состоял, что раз gen_id(gen, 0) носит чисто информативный характер, Max(ID)+1 тоже нельзя, и получить ID, сгенерированный только что сервером тоже нельзя, то вот как раз вопрос в том и состоит, КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
не стыкуется вот это:
www.ibase.ru/devinfo/generator.htm
"специальный объект базы данных, который генерирует уникальные последовательные числа"
"...гарантируется, что каждому пользователю будет всегда возвращено уникальное значение генератора.."
"В результате при создании новой записи полю CLIENT_ID будет автоматически присваиваться новое значение"
"Поскольку SQL-сервер не может сообщить клиентскому приложению о новом значении ключевого поля, необходимо сначала запросить уникальное значение с сервера, и только затем использовать его во вставляемой записи."
ПЕРЕВОЖУ:
Генераторы используются для суррогатных ключей, то есть для выдачи уникальных абстрактных номеров записям. Есть два способа помещения такого уникального номера в запись:
1. в триггере. Этот способ подходит, когда надо вставить запись, и все. То есть, главное - обеспечить уникальность идентификатора, т.к. нам пофиг, какое значение он получает.
2. получить на клиента новое значение (gen_id(x, 1)). Вставить его в запись. Здесь тоже "пофиг" значение, т.к. оно абстрактное, но его надо "показать" клиенту или приложению.
Я согласен, что статью про генераторы надо немножко переписать. Чтобы "и даже карапуз" понял. Но вообще-то, предполагается что человек, который ее читает, понимает механизмы клиент-сервера, то есть, как сервер общается с клиентом.
и этоУважаемый kdv, я все понимаю про ГенИД,
лично мне непонятно, как можно утверждать что все понял, и тут же задавать такие вопросы. Ладно, я уже второй день добрый. Цитирую себя же:КАК ЖЕ МОЖНО ТОГДА вставить запись с уникальным номером и к чему тогда генераторы???
www.ibase.ru/devinfo/generator.htm
"специальный объект базы данных, который генерирует уникальные последовательные числа"
"...гарантируется, что каждому пользователю будет всегда возвращено уникальное значение генератора.."
"В результате при создании новой записи полю CLIENT_ID будет автоматически присваиваться новое значение"
"Поскольку SQL-сервер не может сообщить клиентскому приложению о новом значении ключевого поля, необходимо сначала запросить уникальное значение с сервера, и только затем использовать его во вставляемой записи."
ПЕРЕВОЖУ:
Генераторы используются для суррогатных ключей, то есть для выдачи уникальных абстрактных номеров записям. Есть два способа помещения такого уникального номера в запись:
1. в триггере. Этот способ подходит, когда надо вставить запись, и все. То есть, главное - обеспечить уникальность идентификатора, т.к. нам пофиг, какое значение он получает.
2. получить на клиента новое значение (gen_id(x, 1)). Вставить его в запись. Здесь тоже "пофиг" значение, т.к. оно абстрактное, но его надо "показать" клиенту или приложению.
Я согласен, что статью про генераторы надо немножко переписать. Чтобы "и даже карапуз" понял. Но вообще-то, предполагается что человек, который ее читает, понимает механизмы клиент-сервера, то есть, как сервер общается с клиентом.
Если я правильно понял вопрос, необходимо получить идентификатор добавленной записи?
Я делаю так:
* Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию
Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Так?
ЗЫЖ мое приложение на C#, как это программируется в Access я не знаю.
Я делаю так:
* Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию
Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Так?
ЗЫЖ мое приложение на C#, как это программируется в Access я не знаю.
это понятно, только max(id) тут вообще не нужен. Неужели так трудно получить новый идентификатор, а потом его вставить в запись?Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию
Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Не очень понятно, какое спокойствие ты себе так обесеспечиваешь. Если с твоей БД работают неосторожные разработчики, то они и при твоей схеме могут понаделать все, что угодно. Схема работы с генераторами, предложенная в вышеприведенных ссылках и удобнее и надежнее. Просто необходимо корпоративное соглашение Ваших разработчиков ее использовать.Lokki писал(а):Нет, не трудно.
Просто у меня с одной БД могут работать несколько программ написанных разными людьми, поэтому мне удобнее присваивать идентификаторы средствами БД, а не отдавать на откуп программерам.
Спокойнее как-то :)
Всем огромное спасибо - разобрался
Все оказалось очень просто
Вот примерно такую функцию для получения номера заварганил (может кому сгодится еще)
' создаем 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)
Потом этот номер уже и вставляю куда нужно
Все оказалось очень просто
Вот примерно такую функцию для получения номера заварганил (может кому сгодится еще)
' создаем 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)
Потом этот номер уже и вставляю куда нужно
Достаточно быстрая работа в таком ключе стоит дополнительного descending index-а по ID. Ладно, предположим, начиная с FB1.5 можно сделать PK на descending индексе. Но это всё равно затратнее и тормознее одного обращения к генератору до вставки. Никто не мешает оставить в триггере страховку if (New.ID Is Null) then New.ID=Gen_ID.Lokki писал(а):Если я правильно понял вопрос, необходимо получить идентификатор добавленной записи?
Я делаю так:
* Открываю транзакцию не ниже SNAPSHOT
* Добавляю запись
* SELECT MAX(ID) FROM MY_TABLE;
* Коммичу транзакцию
Т.к. при таком уровне транзакции я вижу состояние БД на момент начала транзакции + изменения внутри моей транзакции, то максимальный ID, будет тем, который присвоен вставленной записи.
Так?
Блоб
добрый день
Люди добрые скажите как получить картинка с блоб тип данных в эксель
использую для этих цель IBEXPERT Любое Блоб не экспортируется.
в базе есть картинки в поле блоб . они крайне важный для работе но их видет кроме как в ибэксперт не получается . хотелось бы всё экспортировать
Люди добрые скажите как получить картинка с блоб тип данных в эксель
использую для этих цель IBEXPERT Любое Блоб не экспортируется.
в базе есть картинки в поле блоб . они крайне важный для работе но их видет кроме как в ибэксперт не получается . хотелось бы всё экспортировать