Страница 1 из 4

Получить NREC после вставки записи (ADO)

Добавлено: 06 окт 2008, 11:49
ilshat
Используя ADO вставляю запись

Код: Выделить всё

insert into t$plpor
(
f$nodok,
f$tidk,
f$tidkgal,
f$sumplat,
f$namepl1
)
values
(
:nodok,
:tidk,
:tidkgal,
:sumplat,
:namepl1
)
NREC генерируется автоматом. Но как его теперь узнать???

Добавлено: 07 окт 2008, 15:35
Galex
По-подробней можно?.. Чем вставляете то?.. Если Delphi, то, если мне не изменяет память, после вставки набор данных должен позиционироваться на новую запись...

Добавлено: 08 окт 2008, 09:04
ilshat
Delphi... Пытался вставить с помощью тейбл и с помощью квери... Когда вставляю тейблом после инсерта нахожусь как раз на новой записи, да только вот NREC как был 0, так и остается :(

Добавлено: 08 окт 2008, 10:11
Galex
А вы уверены, что NREC автоматически генерируется?.. Если платформа Pervasive, то там нет автоинкрементных полей, как мне кажется... Если Галактика сама NREC генерирует...

Добавлено: 08 окт 2008, 12:15
Ged
Да нет у него походу MsSQL
Nrec в тригере генериться.
по идее Nrec инкрементируется. т.е. последний ваш.

Добавлено: 08 окт 2008, 13:18
Den
раньше (в версиях 5,8Х), помню в триггерах скуля были ветка на того, кто лезет :
-галактический коник...
-кто то со стороны

и как то вроде работала вставка извне. Сейчас глянул - в 81 точно триггер поменян по сравнению с тем, что было.
Но насколько мне известно, тебе не заюзать будет нрек, генерируемый в триггере поскольку лезя туда со своей проги ты не будешь "галактическим коником" и :
exec master..na_getnextnrec @db_name,<код таблицы>,@ATL_NREC output,@needmax output

будет возвращаеть просто в @ATL_NREC null

Для того, что бы это все работало нужно приконнектиться своей прогой к сервису NA и сделать как то галактическим процесс твой.Тогда эти ESP,вызываемые из dll, отрабатывать будут, по идее.

Может это тебе поможет, но это есть, конечно же, не самый хороший вариант :

CREATE FUNCTION GenerateNextNrec (@FromCurrentNrec Binary( 8 ))
RETURNS binary( 8 )
AS
BEGIN
Declare @NextNrec binary( 8 ), @index int
Set @index = 8
-- ищем самый мл.байт отличный от 0xFF=255, чтобы потом не развлекаться с переносами из байта в байт; (его и будем увеличивать на 1)
While @index>1 and SubString(@FromCurrentNrec, @index, 1) = 0xFF begin
Select @index = @index-1
end
-- найденный байт увеличится на 1; более младшие байты обнулятся
Select @NextNrec = SubString(@FromCurrentNrec, 1, @index-1) -- неменяющшийся кусочек NREC'а
+ cast(cast(SubString(@FromCurrentNrec, @index, 1) as int)+1 as binary(1)) -- этот байт увеличился на 1 (только через преобразование к числу и обратно)
+ 0x0000000000000000 -- остальные байты заполняем нулями; больше чем 8(!) в binary( 8 ) всё равно не влезет, поэтому
-- нет необходимости заботиться о вычислении требуемого количества
RETURN @NextNrec
END

SELECT dbo.GenerateNextNrec (0x800A00000000976A)

Хотя может я не и не прав, и эти функции из na_ можно как то заюзать проще :???:

Добавлено: 08 окт 2008, 16:59
ilshat
У нас MSSQL. Триггер отрабатывает и через суппорт NREC я вижу. Все нормально сгенерился как положено. Есть конечно совсем колхозный метод: Insert - Close - Open - Last... Если за это время никто не успеет вставить запись в plpor последняя запись моя и NREC вижу... Только шатко все это.

Добавлено: 08 окт 2008, 17:31
Den
Вроде как при использовании ADO в дельфях автоматом создается DataSet-компонент. Собственно после вставки, я так понимаю, текущая запись dataset и будет только что вставленная, со всеми доступными полями....

Добавлено: 08 окт 2008, 17:53
ilshat
В теории именно так и есть... на практике вижу только ноль :(

Добавлено: 08 окт 2008, 18:07
WiRuc
Den писал(а):раньше (в версиях 5,8Х), помню в триггерах скуля были ветка на того, кто лезет :
-галактический коник...
-кто то со стороны

и как то вроде работала вставка извне. Сейчас глянул - в 81 точно триггер поменян по сравнению с тем, что было.
Но насколько мне известно, тебе не заюзать будет нрек, генерируемый в триггере поскольку лезя туда со своей проги ты не будешь "галактическим коником" и :
exec master..na_getnextnrec @db_name,<код таблицы>,@ATL_NREC output,@needmax output

будет возвращаеть просто в @ATL_NREC null

Для того, что бы это все работало нужно приконнектиться своей прогой к сервису NA и сделать как то галактическим процесс твой.Тогда эти ESP,вызываемые из dll, отрабатывать будут, по идее.

Может это тебе поможет, но это есть, конечно же, не самый хороший вариант :

CREATE FUNCTION GenerateNextNrec (@FromCurrentNrec Binary( 8 ))
RETURNS binary( 8 )
AS
BEGIN
Declare @NextNrec binary( 8 ), @index int
Set @index = 8
-- ищем самый мл.байт отличный от 0xFF=255, чтобы потом не развлекаться с переносами из байта в байт; (его и будем увеличивать на 1)
While @index>1 and SubString(@FromCurrentNrec, @index, 1) = 0xFF begin
Select @index = @index-1
end
-- найденный байт увеличится на 1; более младшие байты обнулятся
Select @NextNrec = SubString(@FromCurrentNrec, 1, @index-1) -- неменяющшийся кусочек NREC'а
+ cast(cast(SubString(@FromCurrentNrec, @index, 1) as int)+1 as binary(1)) -- этот байт увеличился на 1 (только через преобразование к числу и обратно)
+ 0x0000000000000000 -- остальные байты заполняем нулями; больше чем 8(!) в binary( 8 ) всё равно не влезет, поэтому
-- нет необходимости заботиться о вычислении требуемого количества
RETURN @NextNrec
END

SELECT dbo.GenerateNextNrec (0x800A00000000976A)

Хотя может я не и не прав, и эти функции из na_ можно как то заюзать проще :???:
Не прав.
Можно спокойно юзать na_xxx из своих запросов. Напишите ХП , которая дергает na_getnextnrec и будете спокойно получать следующий NREC. Все остальные способы - от лукавого.

Добавлено: 08 окт 2008, 18:48
Den
Wiruc, просто как то пробал из QA напрямую :

declare @needmax int,@db_name varchar(30)
DECLARE @F$NREC BINARY( 8 )
select @needmax=0
select @db_name=upper(db_name())
SET @F$NREC = cast(0 as binary( 8 ))

exec master..na_getnextnrec @db_name,9011,@F$NREC output,@needmax output
select @F$NREC,@needmax

но ниче не получил в ответ :-(

Добавлено: 09 окт 2008, 00:19
WiRuc
Вот 100% работающая на 7.12 ХП для генерации нового NREC.
Генерируете нрек перед вставкоц и явно указываете его в команде инсерт.

Код: Выделить всё

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*  Получение нового NREC для таблицы
	Возвращает 0 в случае удачи или 1 в случае неудачи */
CREATE  PROCEDURE [dbo].[up_sys_newnrec] (
	@tableid int,			-- [IN] код таблицы из X$FILES, для которой генерируется NREC
	@newnrec comp OUTPUT )	-- [OUT] возвращает новый NREC или NULL в случае неудачи */
AS
SET NOCOUNT ON
SET XACT_ABORT ON

DECLARE @F$NREC comp, @OriginOffice int, @needmax int, @db_name varchar(30)
SET @F$NREC=0x8000000000000000
SET @needmax=0
SET @db_name=UPPER(DB_NAME())
SET @newnrec = NULL

if @tableid is NULL OR @tableid=0
begin
  exec up_sys_raiseinvalidcall @@procid
  return 1
end

-- Получаем номер офиса
SELECT @OriginOffice=OfficeNo FROM X$JournalConfig
IF @OriginOffice IS NULL
  SET @OriginOffice=0

-- Получаем следующий номер через вызов extended ХП
exec master..na_getnextnrec @db_name,@tableid,@F$NREC output,@needmax output
if @@error<>0
begin
  exec up_sys_raisefatalerror @@procid, 'Ошибка при вызове na_getnextnrec'
  return 1
 end

-- Нужен последний номер для инициализации счетчика NREC
if @needmax=1
begin
  declare @max#F$NREC comp, @csql nvarchar(200), @cparam nvarchar(50)
  set @csql=N'SELECT @max#F$NREC=MAX(F$NREC) FROM '+dbo.uf_sys_gettablenamebycode(@tableid, 1)+N' where convert(int,substring(F$NREC,1,2))=(@OriginOffice|0x8000)'
  set @cparam=N'@max#F$NREC binary(8) OUT, @OriginOffice int'
      
  exec sp_executesql @csql, @cparam, @max#F$NREC OUT, @OriginOffice
  if @@error<>0
  begin
	exec up_sys_raisefatalerror @@procid, 'Ошибка при вызове динамик-SQL'
	return 1
  end
       
  if @max#F$NREC is null
	set @max#F$NREC=0x8000000000000000
       
  exec master..na_getnextnrecbymax @db_name,@tableid,@F$NREC output,@needmax output,@max#F$NREC
  if @@error<>0
  begin
	exec up_sys_raisefatalerror @@procid, 'Ошибка при вызове na_getnextnrecbymax'
	return 1
  end
end

-- Проверка ошибок
if @needmax IN (255,254,253) OR @F$NREC IS NULL OR @F$NREC=0x8000000000000000
begin
  exec up_sys_raisefatalerror @@procid, 'Ошибка генерации NREC'
  return 1
end

-- Добавляем номер офиса к значению NREC
set @newnrec=convert(binary(2),@OriginOffice|0x8000)+substring(@F$NREC,3,6)

return 0
GO

Добавлено: 09 окт 2008, 15:00
ilshat
Спасибо! Буду пробовать

Добавлено: 13 окт 2008, 15:16
ilshat

Код: Выделить всё

Msg 2715, Level 16, State 3, Procedure up_sys_newnrec, Line 3
Column, parameter, or variable #2: Cannot find data type comp.
Parameter or variable '@newnrec' has an invalid data type.
Msg 2715, Level 16, State 3, Procedure up_sys_newnrec, Line 3
Column, parameter, or variable #3: Cannot find data type comp.
Parameter or variable '@F$NREC' has an invalid data type.
Msg 2715, Level 16, State 3, Procedure up_sys_newnrec, Line 3
Column, parameter, or variable #7: Cannot find data type comp.
Parameter or variable '@max#F$NREC' has an invalid data type.
вот так отругался ms sql на процедуру

Добавлено: 13 окт 2008, 16:42
Den
тип данных comp реально в варинте БД MSSQl Галактики хранятся как binary( 8 )...