powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / GetIdentity
25 сообщений из 33, страница 1 из 2
GetIdentity
    #33079765
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
добрый день!
[pb9.01, msSqlServer 2000, провайдер: oledb / MSS Microsoft SQL Server]
Проблема: добыча значения первичного ключа после сохранения изменений datawindow (dw.update()) -- для связи таблиц master-detail.

Каким образом можно добыть значение identity-столбца (столбца со встроенным инкрементом) после успешного update'а datawindow'ы? я пробовал такие варианты:
1. описание указанного автоинкрементного столбца в dw-painter'е как identity column.
Недостаток: новое значение id-столбца считыывается как
Код: plaintext
select MAX(IDENTITYCOL)
,
либо вместо IDENTITYCOL ставится название колонки. Я до сих пор не могу представить себе, кто ваще мог до этого додуматься! это же только для однопользовательской системы можно считывать максимальное значение, но если два пользователя добавят по записи, то возможны "коллизии".

2. после успешного dw.update() можно сделать
Код: plaintext
select idcol from atable where atable.idcol=scope_identity()
(выражение типа select scope_identity() в pb-script'е не проходят!)
Недостаток: нельзя унифицировать эту datawindow, т.е. сделать класс, при использовании которого указываешь таблицу, id-столбец, а он, класс, сам выполняет нужную работу.. так вот, динамический select не возвращает нужное scope_identity(),
Код: plaintext
select ... @@identity 
а не всегда подходит, так как если на таблице весит триггер, который добавляет ещё куда-то записи, то он собьёт значение @@identity.

Поэтому у меня пара вопросов
если ли для провайдеров pbmssXX.dll и pboleXX.dll настройки, как для ODBC-провайдера? (pbodbXX.ini) то есть, как повлиять на параметр GetIdentity ?

у кого как реализовано считывание значения уникальной колонки до или после сохранения изменений в datawindow?

Несколько решений уже было высказано , а именно:

генерация значения ключевого поля во вспомогательной хранимой процедуре/таблице

генерация id "вручную" -- с шагом 300, со сдвигом, равным номеру соединения с сервером (способ, который я предложил к обсуждению, и который никому не понравился)

сохранять все связи в datastore (например, с использованием отрицательных значений для ключевых полей), а при сохранении считывать id у мастера, присваивать их в foreign key подч. таблицы. Опять же, надо считывать @@identity или identity_scope() из БД -- потеря универсальности!

перенести всю логику сохранения таблицы на хранимые процедуры! и передавать им нужные значения. Недостаток: никакой универсальности (на мой, конечно же, взгляд) -- для каждой таблицы, или даже пары таблиц master-detail, а то и вообще для каждого документа, придётся делать сдециальные хранимые процедуры
...
Рейтинг: 0 / 0
GetIdentity
    #33080003
Фотография ЗоринАндрей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
(выражение типа select scope_identity() в pb-script'е не проходят!
Код: plaintext
1.
2.
3.
4.
5.
6.
string ls_sql = "SELECT scope_identity()"
DECLARE aa_cur DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :ls_sql	USING SQLCA;
OPEN DYNAMIC aa_cur;
FETCH aa_cur	INTO :ll_result;
CLOSE aa_cur ;
...
Рейтинг: 0 / 0
GetIdentity
    #33080113
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЗоринАндрей
Код: plaintext
DECLARE aa_cur DYNAMIC CURSOR FOR SQLSA;

у динамического курсора контекст другой, и select scope_identity() вернёт NULL (хотя select @@identity сработает нормально, так как он от контекста не зависит).
...
Рейтинг: 0 / 0
GetIdentity
    #33080134
Dim2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergeyНедостаток: новое значение id-столбца считыывается как
Код: plaintext
select MAX(IDENTITYCOL)
,
либо вместо IDENTITYCOL ставится название колонки. Я до сих пор не могу представить себе, кто ваще мог до этого додуматься!
Люди не глупее тебя ;). Я весьма смутно помню обсуждение этой проблемы (давно это было), но не всё так просто, как кажется :).

(выражение типа select scope_identity() в pb-script'е не проходят!)
В M$SQL есть аналог DUMMY из ASA или DUAL из Оракла? Ибо
Код: plaintext
SELECT scope_identity() into :id from dummy;
эхотаг проглотит.
...
Рейтинг: 0 / 0
GetIdentity
    #33080343
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторЛюди не глупее тебя ;). Я весьма смутно помню обсуждение этой проблемы (давно это было), но не всё так просто, как кажется :).
вот-вот, по-подробнее можно? max() он и есть max().. если только таблицу/запись не блокировать от других пользователей.. интересно, что ODBC-провайдер обращается за последним значением ключевого поля как
Код: plaintext
select @@identity
,
а oledb и mssqlserver - провайдеры всего лишь как
Код: plaintext
select max(identitycol)

Dim2000В M$SQL есть аналог DUMMY из ASA или DUAL из Оракла? Ибо
SELECT scope_identity() into :id from dummy;

эхотаг проглотит. Server: Msg 208, Level 16, State 1, Line 1
Invalid object name 'dummy'.
...
Рейтинг: 0 / 0
GetIdentity
    #33080353
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторВ M$SQL есть аналог DUMMY из ASA или DUAL из Оракла? Ибо
Код: plaintext
SELECT scope_identity() into :id from dummy;
эхотаг проглотит.
ой, не заметил, что этотаг = powerBuilder
Код: plaintext
1.
2.
long id

SELECT scope_identity() into :id from dummy;
возвращает при Compile
Database C0038: Invalid object name 'dummy'.
...
Рейтинг: 0 / 0
GetIdentity
    #33080380
Фотография ЗоринАндрей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergeyу динамического курсора контекст другой, и select scope_identity() вернёт NULL Проверял? Или это только теоретическое предположение?
Четыре года назад, когда в какой-то из версий девятки OLEDB не читал identity вообще, мы именно так извлекали значение identity для свежедобавленных строк.
...
Рейтинг: 0 / 0
GetIdentity
    #33080452
Dim2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergeyвот-вот, по-подробнее можно?
Нельзя :). Если серьёзно - это было слишком давно, чтобы я помнил подробности :(.

Server: Msg 208, Level 16, State 1, Line 1
Invalid object name 'dummy'.

Ну так я сразу признался, что M$SQL знаю ;). Если ничего похожего на DUMMY из ASA в нём нет - тогда см. письмо Андрея Зорина.
...
Рейтинг: 0 / 0
GetIdentity
    #33080474
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergeyвозвращает при Compile
Database C0038: Invalid object name 'dummy'.
dummy в MS SQL нет

Возьмите что-нибудь из системного:
авторlong id

SELECT TOP 1 scope_identity() into :id from syscolumns;
savosin_sergeyа не всегда подходит, так как если на таблице весит триггер, который добавляет ещё куда-то записи, то он собьёт значение @@identity.
В триггере можно значения и восстанавливать.
...
Рейтинг: 0 / 0
GetIdentity
    #33080482
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЗоринАндрей savosin_sergeyу динамического курсора контекст другой, и select scope_identity() вернёт NULL Проверял? Или это только теоретическое предположение?
Четыре года назад, когда в какой-то из версий девятки OLEDB не читал identity вообще, мы именно так извлекали значение identity для свежедобавленных строк.
признаю -- я был не прав! действительно, если провайдер = MSOLEDB, то возвращает нужное значение это динамичесвий курсор!
лог profiler'а:
Код: plaintext
insert into bu_test ( name1 ) values ( 'ar' ) 
Код: plaintext
IF @@TRANCOUNT >  0  COMMIT TRAN
Код: plaintext
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Код: plaintext
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
Код: plaintext
SELECT scope_identity()
--------------------------------

а если провайдер = ms sql server, то в профайлере видно:
Код: plaintext
insert into bu_test ( name1 ) values ( 'ar' ) 
Код: plaintext
commit tran
Код: plaintext
begin tran
Код: plaintext
declare @P1 int
Код: plaintext
1.
2.
3.
4.
5.
6.
set @P1= 180150003 
declare @P2 int
set @P2= 8 
declare @P3 int
set @P3= 1 
exec sp_cursoropen @cursor = @P1 output, @stmt = 'SELECT scope_ide', @scrollopt = @P2 output, @ccopt =  4 , @rows = @P3 output
select @P1, @P2, @P3
Код: plaintext
exec sp_cursorfetch @cursor =  180150003 , @fetchtype =  1 , @rownumber = [src] 0 , @nrows =  1 
exec sp_cursorclose @cursor = 180150003[/src]---------------------------------
...
Рейтинг: 0 / 0
GetIdentity
    #33080487
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
..и в провайдере ms sql server select scope_identity() в динамическом курсоре возвращает NULL..
...
Рейтинг: 0 / 0
GetIdentity
    #33080923
Фотография Филипп
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergey..и в провайдере ms sql server select scope_identity() в динамическом курсоре возвращает NULL..
А если не морочиться с динамическим курсором, и сделать RPC FUNC?
...
Рейтинг: 0 / 0
GetIdentity
    #33081480
Фотография ChV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может не совсем в тему, но если в схожей ситуации решил эту проблему несколько иначе :
1. В "detail" таблице добавляю строку с данными.
2. Триггер "detail" таблицы добавляет строку с данными ( в том числе и с ключем из "detail" таблицы в "master" таблицу )
...
Рейтинг: 0 / 0
GetIdentity
    #33081518
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChVМожет не совсем в тему, но если в схожей ситуации решил эту проблему несколько иначе :
1. В "detail" таблице добавляю строку с данными.
2. Триггер "detail" таблицы добавляет строку с данными ( в том числе и с ключем из "detail" таблицы в "master" таблицу )
то есть, при вводе новой строки в detail добавляется новая строка в master? как это? обычно пользователь сначала вводит заголовок документа (=master-таблица), а потом перечень позиций документа (=detail-таблица). Так что непонятно, откуда триггеру (на подчинённой таблице) знать id главной таблицы..
...
Рейтинг: 0 / 0
GetIdentity
    #33081628
Фотография ChV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergey
то есть, при вводе новой строки в detail добавляется новая строка в master? как это? обычно пользователь сначала вводит заголовок документа (=master-таблица), а потом перечень позиций документа (=detail-таблица). Так что непонятно, откуда триггеру (на подчинённой таблице) знать id главной таблицы..
При такой последовательности действий - конечно - "откуда". Но не пользователь работает не с БД, а программы, написанные нами. Что мешает вначале создать связанные записи в обеих таблицах, а потом заполнять их вводимой информацией ? Конечно я не знаю особенностей Вашей задачи. Могу только более описать как решил свои проблемы.
...
Рейтинг: 0 / 0
GetIdentity
    #33081862
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ФилиппА если не морочиться с динамическим курсором, и сделать RPC FUNC? что-то не получается у меня сделать RPCFUNC для функции mss2000, а оборачивать её в ХП нет смысла, так как контекст изменится!

ChVМогу только более описать как решил свои проблемы. Если не сложно!
...
Рейтинг: 0 / 0
GetIdentity
    #33082009
alexis glinski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
savosin_sergeyчто-то не получается у меня сделать RPCFUNC для функции mss2000, а оборачивать её в ХП нет смысла, так как контекст изменится!
У меня так:
1. хранимая процедура в БД:
Код: plaintext
1.
2.
CREATE PROCEDURE sp_GetIdentity @ret_val int OUTPUT AS
SET @ret_val = @@IDENTITY
GO
2. RPC function declaration (local external function) in transaction object n_tr_app :
Код: plaintext
function long sp_GetIdentity(ref long ret_val) RPCFUNC ALIAS FOR "dbo.sp_GetIdentity"
3. для удобства обычная функция в этом же объекте ( n_tr_app ):
Код: plaintext
1.
2.
3.
4.
5.
6.
public function long of_getidentity ();
long	ll_Ret, ll_Identity

ll_Ret = sp_GetIdentity( ll_Identity )

RETURN ll_Identity
end function

PB6.5.1
...
Рейтинг: 0 / 0
GetIdentity
    #33082103
Фотография ChV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне досталась "в наследство" база ( MS SQL ) с такой организацией : в одной таблице ( назовем "status" ) хранится общая информация записей нескольких таблиц ( назовем "tab...") с разной структурой. Запись в таблица Status содержит ключ таблицы tab... ( назовем id_tab ) ,её тип и т.д.
Проблема создания - уничтожения связанных записей решалась с помощью триггеров.
Создание: В каждой таблице tab...( создающей для каждой строки уникальный ключ "ident" ) прописан триггер
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TRIGGER tr_add_tab... ON dbo.tab… 
FOR INSERT
AS
DECLARE @ident decimal( 18 )

SELECT @ident = ident, … FROM INSERTED
...

INSERT INTO Status (… , id_tab)   VALUES( … , @ident )  
Хочется сразу сказать, что использовать @@identity нельзя, т.к. он будет возвращать создаваемый ключ таблицы Status.
Всё.
Таким образом я создаю запись только в таблице Tab..., а уже потом (после dw.retrieve()) вношу изменения в таблицу Tab... или Status ( dw.update()).
Всё.
...
Рейтинг: 0 / 0
GetIdentity
    #33082351
Фотография ChV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChVМне досталась "в наследство" база ( MS SQL ) с такой организацией : в одной таблице ( назовем "status" ) хранится общая информация записей нескольких таблиц ( назовем "tab...") с разной структурой. Запись в таблица Status содержит ключ таблицы tab... ( назовем id_tab ) ,её тип и т.д.
Проблема создания - уничтожения связанных записей решалась с помощью триггеров.
Создание: В каждой таблице tab...( создающей для каждой строки уникальный ключ "ident" ) прописан триггер
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TRIGGER tr_add_tab... ON dbo.tab… 
FOR INSERT
AS
DECLARE @ident decimal( 18 )

SELECT @ident = ident, … FROM INSERTED
...

INSERT INTO Status (… , id_tab)   VALUES( … , @ident )  
Хочется сразу сказать, что использовать @@identity нельзя, т.к. он будет возвращать создаваемый ключ таблицы Status.
Таким образом я создаю запись только в таблице Tab..., а уже потом (после dw.retrieve()) вношу изменения в таблицу Tab... или Status ( dw.update()).
Всё.Sorry ! Хочу уточнить "использовать @@identity нельзя" вне триггера. А в самом триггере, он должен отработать правильно - уже давно было - проблемы помню, а нюансы подзабыл.
...
Рейтинг: 0 / 0
GetIdentity
    #33082878
Фотография ЗоринАндрей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ChVSorry ! Хочу уточнить "использовать @@identity нельзя" вне триггера. А в самом триггере, он должен отработать правильно - уже давно было - проблемы помню, а нюансы подзабыл.Спросите у Марка - он знает способ как восстановить значение @@identity в триггере.
там три или четыре строчки всего. и никаких извратов.
...
Рейтинг: 0 / 0
GetIdentity
    #33082937
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот, соранить значение @@identity в начале триггера, а в конце вызвать процедуру:
Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE PROCEDURE dbo.usp_SetIdentityValue (@val bigint)
AS 
BEGIN 
  declare @sqlsyntax nvarchar( 4000 )
  set @sqlsyntax='select identity(bigint,'+cast(@val as VARCHAR)+',1) id into #t_SetIdentVal'
  EXEC(@sqlsyntax) 
END

Догадаться до идеи не сложно. Но авторство метода не мое...
...
Рейтинг: 0 / 0
GetIdentity
    #33083012
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Какой все таки это тяжелый процесс, получить инкремент с MSSQL :( Интересно, в Юконе будет эта проблема решена "культурным путем" или же в игру еще C# включится.
...
Рейтинг: 0 / 0
GetIdentity
    #33083162
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ASCRUSКакой все таки это тяжелый процесс, получить инкремент с MSSQL :( Интересно, в Юконе будет эта проблема решена "культурным путем" или же в игру еще C# включится.
Так давно уже все решено - SCOPE_IDENTITY( )
...
Рейтинг: 0 / 0
GetIdentity
    #33083170
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
... а то, что какая-то отдельная программа какой-то отдельной фирмы не дает им без некоторых выкрутасов пользоваться, по-моему Microsoft волновать и не должно.
...
Рейтинг: 0 / 0
GetIdentity
    #33083223
Фотография savosin_sergey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если провайдер ms oledb, то с помощью динамического курсора scope_identity() нормально извлекается.. хотя и
Код: plaintext
1.
2.
dw.update()

select id_col into :long_id from a_table where id_col=scope_identity
тоже нормально работает (хотя и содержит ображение к таблице, но зато по индексированному полю)
-------------------

Меня волновал в начале темы такой вопрос: использует ли кто свойство DW identity column? ведь (для oledb-, mssqlserver- провайдеров) оно считывает первичный ключ как max(имя_колонки)..

и второе: если не используется это identity column, то какая альтернатива в реальных программах этому есть?

на первый вопрос более-менее вразумительно ответил лишь
Dim2000Люди не глупее тебя ;). Я весьма смутно помню обсуждение этой проблемы (давно это было), но не всё так просто, как кажется :).

а ответы на второй вопрос до сих пор интересуют меня! видимо, основные решения я сам перечислил (набранные с других тем)
...
Рейтинг: 0 / 0
25 сообщений из 33, страница 1 из 2
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / GetIdentity
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]