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

Программирование на Атлантисе (VIP, FCOM, ARD), FastReport

Модераторы: m0p3e, edward_K, Модераторы

ilshat
Местный житель
Сообщения: 222
Зарегистрирован: 04 июн 2008, 14:35
Откуда: Стерлитамак
Контактная информация:

Сообщение ilshat »

Работало нормально все и вдруг:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.uf_sys_gettablenamebycode", or the name is ambiguous.
Все теперь не работает :(
WiRuc
Местный житель
Сообщения: 414
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж

Сообщение WiRuc »

ilshat писал(а):Работало нормально все и вдруг:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.uf_sys_gettablenamebycode", or the name is ambiguous.
Все теперь не работает :(
Это потому, что теперь сработала ветка

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

-- Нужен последний номер для инициализации счетчика NREC
if @needmax=1 
в которой используется такая функция. Эта функция возвращает имя таблицы по ее коду банальным селектом из x$tables. Напишите сами или я вечером выложу исходник.
ilshat
Местный житель
Сообщения: 222
Зарегистрирован: 04 июн 2008, 14:35
Откуда: Стерлитамак
Контактная информация:

Сообщение ilshat »

Я не силен в mssql. Если не трудно выложите функцию.
WiRuc
Местный житель
Сообщения: 414
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж

Сообщение WiRuc »

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

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Словарь БД (таблицы)
CREATE    view [dbo].[v_dict_tables] as
select sys#nrec as nrec, xf$code as code, xf$name as name, (CASE WHEN xf$code<100 THEN xf$name ELSE 'T$'+xf$name END) as sysname, xf$title as note, xf$loc2 as unit, xf$flags as flags, xf$attr as attr, CAST(CASE WHEN xf$loc2='user' THEN 1 ELSE 0 END as bit) as is_temporary, CAST(CASE WHEN xf$code<100 THEN 1 ELSE 0 END as bit) as is_system, (CASE WHEN xf$flags&512>0 THEN 'J$'+LTRIM(STR(xf$code,10)) ELSE null END) as journal_table_name from x$files where xf$code>0
GO
ET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Возвращает наименование таблицы по ее коду
CREATE  function [dbo].[uf_sys_GetTableNameByCode] (
	@tablecode int,	-- код таблицы
	@type bit=1 )	-- что возвращаем (0 - имя таблицы в словаре, 1 - имя в БД)
returns galname
as
begin
return (select (CASE WHEN @type=0 THEN name ELSE sysname END) from dbo.v_dict_tables where code=@tablecode)
end
GO
ilshat
Местный житель
Сообщения: 222
Зарегистрирован: 04 июн 2008, 14:35
Откуда: Стерлитамак
Контактная информация:

Сообщение ilshat »

ошибка :(

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

Column, parameter, or variable #0: Cannot find data type galname.
Parameter or variable '' has an invalid data type.
WiRuc
Местный житель
Сообщения: 414
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Воронеж

Сообщение WiRuc »

ilshat писал(а):ошибка :(

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

Column, parameter, or variable #0: Cannot find data type galname.
Parameter or variable '' has an invalid data type.
galname замените на sysname
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vik »

А как бы это все дело в виде функции оформить, корифеи TransactSQL не подскажут? Просто sp_executesql внутри функции работать отказывается (
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Сообщение Den »

По видимому нужно просто оформить, предложенную Wiruc-ом процедуру up_sys_newnrec в виде функции.
И потом она будет вставлять...

insert T$MDAOBJRLT (f$nrec,f$comment)
select
dbo.up_sys_newnrec(31937)
,case when sopr.f$tidkgal=111 then 'акт на прием услуг'
when sopr.f$tidkgal=101 then 'накладнуха на прием мц'
end
from t$soprhoz sopr
where
.....

как то пробовал специально такой скрипт на job вешать на выполнение кой каких проверок у себя. Вставка отрабатывала.
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vik »

Ну это все понятно) Я ее написал, все хорошо работало, пока однажды не получил @needmax = 1. Сразу же в этом месте :

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

.....
set @cparam=N'@max#F$NREC binary(8) OUT, @OriginOffice int'
  exec sp_executesql @csql, @cparam, @max#F$NREC OUT, @OriginOffice
  if @@error<>0 
......
ругань на то, что exec sp_executesql не может быть выполнен внутри функции..
Polimer
Местный житель
Сообщения: 489
Зарегистрирован: 27 янв 2006, 12:46
Откуда: Москва

Сообщение Polimer »

У нас используется такая ХП для приращения нрек, офис 1.

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

CREATE PROCEDURE spNapSetNREC(@TableNameOrCode VARCHAR(80), @NewNREC VARBINARY(8))
AS
BEGIN
  DECLARE @I INT, @DbName VARCHAR(50), @NeedMax INT, @TableCode INT
  DECLARE @NREC0 VARBINARY(8), @NREC VARBINARY(8), @Base VARBINARY(2)
  SELECT
    @Base = CONVERT(VARBINARY(2), CONVERT(INT, SUBSTRING(@NewNREC, 1, 2)) & 0x8001)
  SELECT 
    @TableCode = dbo.fnTableCode(@TableNameOrCode),
    @DbName = UPPER(DB_NAME()), 
    @NeedMax=0, 
    @NREC0 = SUBSTRING(@Base, 1, 2) + SUBSTRING(0x000000000000, 1, 6), 
    @I = 0
  SELECT
    @NREC = @NREC0

  EXEC master..na_getnextnrec @DbName, @TableCode, @NREC OUTPUT, @NeedMax OUTPUT
  IF @NeedMax = 1 
    EXEC master..na_getnextnrecbymax @DbName, @TableCode, @NREC OUTPUT, @NeedMax OUTPUT, @NewNREC
  ELSE 
  IF @NREC >= @NewNREC
    PRINT 'spNAPSetNREC: NREC успешно приращен'
  ELSE
  BEGIN
    DECLARE @Diff BIGINT, @Msg VARCHAR(8000), @IMax BIGINT
    SELECT 
      @IMax = 1000000, 
      @Diff = CONVERT(BIGINT, @NewNREC) - CONVERT(BIGINT, @NREC)
    IF @Diff > @IMax BEGIN
      SELECT @Msg = 'spNAPSetNREC: приращение NREC на слишком большое значение (' + LTRIM(@Diff) + ')'
      RAISERROR(@Msg, 16, 1)
    END
    ELSE BEGIN
      PRINT 'spNapSetNREC: Вызываю na_getnextnrec в цикле...'
      WHILE @NREC < @NewNREC AND @I <= @IMax
      BEGIN
        SELECT @NREC = @NREC0
        EXEC master..na_getnextnrec @DbName, @TableCode, @NREC OUTPUT, @NeedMax OUTPUT
        SELECT @I = @I + 1
      END
      IF ISNULL(@NREC, 0) < @NewNREC 
      BEGIN
        SELECT @Msg = 'Ошибка в spNapSetNREC: ' + CHAR(10) + 
          'NREC не приращен до заданного значения. ' + 
          'Цикл прерван после ' + LTRIM(@I) + ' вызовов na_getnextnrec. ' + CHAR(10) + 
          'Для дополнительного приращения NREC повторно вызовите процедуру ' + 
          'spNapSetNREC.'
        RAISERROR(@Msg, 16, 1)
      END
    END
  END
  IF @NREC = @NewNREC PRINT 'spNapSetNREC: NREC успешно приращен.'
END

GO
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Сообщение Den »

Vik, был невнимателен я. Похоже не все так просто..)
Можно попробовать убрать ,если ты уже оформил в виде функции, в приведенном коде Wiruc-а строки :


....
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
...

По идее дожно работать, но видимо без учета офисности (вернее тока для определенного офиса какого то) , как у Polimer-а ...
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Сообщение Den »

Еще можно попробовать выцеплять нужный @max#F$NREC
посредством view. Создаем скриптом текст вью :

select distinct 'select '+table_name+' table_name,max(f$nrec) from '+table_name+' union '
from information_schema.columns where column_name = 'f$nrec' and substring(table_name,1,2)='t$'

далее создаем create view vmaxtNrec как результат этого. И внутри функции определеяем :
@max#F$NREC =select Nrec from vmaxtNrec where table_name = 'table2'

Но это навскидку - нужно пробовать...
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vik »

Den писал(а):Vik, был невнимателен я. Похоже не все так просто..)
Можно попробовать убрать ,если ты уже оформил в виде функции, в приведенном коде Wiruc-а строки :

...
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
...

По идее дожно работать, но видимо без учета офисности (вернее тока для определенного офиса какого то) , как у Polimer-а ...

Не, убирать нельзя. Иначе будет другая ругань: Дублирование уникального ключа таблицы и так далее) Насчет вьюхи - попробую! А не подскажете, почему, когда делаю инсерт без присваивания нрека одной новой записи, запись вставляется, то есть триггер отрабатывает, а когда несколько - дублирование уникального ключа? Имею ввиду из MSSQL вставка производится.
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Сообщение Den »

Такая вот особенность реализации это. Видимо как то связано с тем, что нреки в напе формируются, а триггер отрабатывает тогда, кода вставка фактически завершена, в частности - модифицированы индексы. Модификация уникальных индексов включает в себя
проверку, т.е. в данном случае просто проверка не пройдёт - все нреки нулевые будут, уникальность соблюдаться не будет. вообщем толком непонятно. Особенность скуля может такая еще...

В любом триггере на ins Вы увидите
-- Check and calculate new NRec value:
IF @RowCount=1 BEGIN

Т.е. если модифицируешь одну запись - то вставка пройдет. Конечно можно однострочную вставку реализовать, но хочется конечно батчем сразу (
Den
Местный житель
Сообщения: 1842
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Ярославская область ОАО "Часовой завод Чайка" г. Углич
Контактная информация:

Сообщение Den »

Vik писал(а): Не, убирать нельзя. Иначе будет другая ругань: Дублирование уникального ключа таблицы и так далее)
Хм..убрал ради интереса. Вроде чирикает все.
Ответить