MAV Direct ODBC

Обсуждение MAV Direct ODBC

Модератор: Andrew™

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion и MAV который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

FREE LIKE режим в конструкторе фильтров

Сообщение Andrew™ »

Новый режим добавлен в конструктор фильтров - FREE LIKE, что означает что введённая конструкция подставляется в LIKE ? as is, единственно введён контроль на длину ввода , если введённое значение больше размера поля в БД по которому производится поиск, введённое значение обрезается до размера поля в БД и вместо LIKE в WHERE конструкцию попадёт обычное сравнение Field=?, иначе просто будет ошибка биндования.
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Мелочь, а приятно

Сообщение Andrew™ »

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

я всё отмахивался, наверняка что то похожее есть и в ABCFree, зачем спрашивается изобретать велосипед. А вот сегодня разродится и сделал. ;)
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

MAVSelect

Сообщение Andrew™ »

тут одну фичу заметил
декларируем курсор

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

tmp  MAVSelect
хотим вытащить только одну запись

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

 tmp.Init(1,1)
 tmp.BindFields(File)
 IF NOT tmp.Run()
   IF NOT tmp.Fetch() 
     ! Вытащили
   END
 END

но далее, если не сделать принудительно tmp.Reset() или tmp.Reset(1) курсор не закрывался на сервере, он продолжал жить пока живёт объект tmp, в деструкторе закрывается.

самое интересное что на MSSQL 2000 ресурс под курсор на сервере автоматом закрывается, т к заказали 1 запись и уже получили 1 запись, и нет смысла держать откытым ресурс


библиотека подрихтована на тему если заказали определённое количество записей и читаем последнюю (ошибки нет, т к по ошибке происходит закрытие) закрываем принудительно курсор
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Автоинкрементные поля

Сообщение Денис »

Вот еще проблема:
У таблицы есть автоинкрементное поле, в словаре ставлю у него Read only.
Так вот если в Init value прописать SELECT @@IDENTITY - все работает, а если Select SCOPE_IDENTITY( ) то нет. В трассе селект отрабатывает но значение поля = 0.
Хочется иметь возможность иметь значение поля с помощью SCOPE_IDENTITY( ), т.к. возможно использование триггеров с добавлением записей в другие таблицы с автоинкрементным полем
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Автоинкрементные поля

Сообщение Andrew™ »

Денис писал(а):Вот еще проблема:
У таблицы есть автоинкрементное поле, в словаре ставлю у него Read only.
Так вот если в Init value прописать SELECT @@IDENTITY - все работает, а если Select SCOPE_IDENTITY( ) то нет. В трассе селект отрабатывает но значение поля = 0.
Хочется иметь возможность иметь значение поля с помощью SCOPE_IDENTITY( ), т.к. возможно использование триггеров с добавлением записей в другие таблицы с автоинкрементным полем
Этот вопрос неодократно подымался, 100% решения получения значенния IDENTITY поля после добавления никто не предложил, вероятность, что через волшебные SELECTы можно получить значения IDENTITY полей <= 100%. В твоём случае Select SCOPE_IDENTITY( ) врозвращает именно НОЛЬ, не считаю это проблемой библиотеки, что заказали то и получили.
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Re: Автоинкрементные поля

Сообщение Денис »

Andrew Myalin писал(а):
Денис писал(а):Вот еще проблема:
У таблицы есть автоинкрементное поле, в словаре ставлю у него Read only.
Так вот если в Init value прописать SELECT @@IDENTITY - все работает, а если Select SCOPE_IDENTITY( ) то нет. В трассе селект отрабатывает но значение поля = 0.
Хочется иметь возможность иметь значение поля с помощью SCOPE_IDENTITY( ), т.к. возможно использование триггеров с добавлением записей в другие таблицы с автоинкрементным полем
Этот вопрос неодократно подымался, 100% решения получения значенния IDENTITY поля после добавления никто не предложил, вероятность, что через волшебные SELECTы можно получить значения IDENTITY полей <= 100%. В твоём случае Select SCOPE_IDENTITY( ) врозвращает именно НОЛЬ, не считаю это проблемой библиотеки, что заказали то и получили.
Помоему сдесь было только твое предложение по поводу Indentity полей - завести отдельную таблицу и самим вычислять очередное значение автоинкремента, а думаю что это неправельно. У сервера есть стандартные средства получения этого значения, их собственно 3. Это SELECT @@IDENTITY, SELECT SCOPE_IDENTITY() и SELECT IDENT_CURRENT('имя таблицы'). Подробно о них можно почитать в BOL.

Что значит "SELECTы можно получить значения IDENTITY полей <= 100%" ? Получается чтобы получить 100% нужно заводить для добавления ХП ? Или как ?
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Автоинкрементные поля

Сообщение Andrew™ »

Денис писал(а):
Andrew Myalin писал(а):
Денис писал(а):Вот еще проблема:
У таблицы есть автоинкрементное поле, в словаре ставлю у него Read only.
Так вот если в Init value прописать SELECT @@IDENTITY - все работает, а если Select SCOPE_IDENTITY( ) то нет. В трассе селект отрабатывает но значение поля = 0.
я приведу лишь цитаты большой переписки на эту тему

> А пробовал ли уважаемый получить значение SCOPE_IDENTITY() из Клариона
> после выполнения ADD(File)? Результатом всегда будет 0, полскольку запрос
> будет уже в другом скопе!

Да, так и будет.

ТШ> Все правильно, если использовать IDENT_CURRENT , поскольку он
ТШ> возвращает последний Indentity таблицы во всех сессиях и скопах,
ТШ> чтобы получить, именно то, что нужно, надо использовать
ТШ> Scope_Indentity(), но вот из
ТШ> Клариона это сделать не получится

потому что это надо делать в одном пакете, т е как уже тут говорилось INSERT
засовывать в ХП,
а ХП будет возвращать новое ID через Scope_Identity()

Вопрос исключительно от полного непонимания (незнания?) SQL-технологий.
В частности - алгоритмов работы SQL-сервера. Объясняю на пальцах, как для
второго курса: операция SQL INSERT выполняет только помещение передаваемых
значений в хранилище. Алгоритм следующий:
1. Прочитать значение Identity-поля из системной таблицы и увеличить на
заданное
значение.
2. Присвоить значение Identity-полю и всем Default-полям.
3. Добавить запись.
Все. Никакого перечитывания. Возвращает только ошибку.
Как же выкручиваются все разработчики? Заменой Insert на соответствующую
хранимую процедуру примерно такого типа:
--=======================================
CREATE PROCEDURE DisciplinaInsert
(@Creator int, @IUMU_Dis_code int = NULL, @IDis_Name varchar(500) = NULL)
AS
BEGIN
SET NOCOUNT ON
DECLARE @SID int, @LDateTime datetime
-- Добавляем
INSERT INTO Disciplina (UMU_Dis_code,
Dis_Name,
StartDate,
EndDate)
VALUES(@IUMU_Dis_code,
@IDis_Name,
DEFAULT,
DEFAULT)
IF @@Error = 0
BEGIN
SET @SID = SCOPE_IDENTITY()
RETURN @SID
END
ELSE
RETURN -1
END
--=====================================

Использовать необходимо именно SCOPE_IDENTITY(), а не @@IDENTITY.
Т.к. значение глобальной переменной @@IDENTITY может быть изменено
из другой сессии.
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Автоинкрементные поля

Сообщение Andrew™ »

Денис писал(а): Помоему сдесь было только твое предложение по поводу Indentity полей - завести отдельную таблицу и самим вычислять очередное значение автоинкремента, а думаю что это неправельно. У сервера есть стандартные средства получения этого значения, их собственно 3. Это SELECT @@IDENTITY, SELECT SCOPE_IDENTITY() и SELECT IDENT_CURRENT('имя таблицы'). Подробно о них можно почитать в BOL.
Ещё нашёлся самый умный, ну раз я предлагаю неправильно, почему у тебя , где всё есть правильно, возникают проблемы на пустом месте?
хочешь использование IDENTITY - не широко мыслишь, сам создаешь себе проблемы, а именно, придётся отказаться от штатных операций добавления INSERT, генерить на каждые такие таблицы ХП на INSERT, и не забывать при этом синхронизировать их при изменении структуры в БД, и их соответсвующие вызовы в программе, это раз

два - забудь при таком подходе про репликации данных, если таковые когда нибудь потребуются, а они в конце концов потребуются, фирма, филиалы и т д.

конечно можно остановится на SELECT @@IDENTITY, но при этом не забудь бубен прикупить для нештатных ситуаций. ;)

если не тв хозяин в проектировке БД и есть такие таблицы то тут уж и в правду деваться не куда, придётся помучатся, если же ты сам хозяин в БД, то нахрена этот гемор?

с моей точки зрения IDENTITY это средство для ленивых, уж если ребятки введи такую возможность почему в той же самой доке по серваку напЫсано что в определённых задачах нельзя использовать IDENTITY механизмов.
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Identity

Сообщение Денис »

По поводу примера, что ты привел. Его я не видел на форуме, так как вопросы разбросаны черте как по форуму. Я знаю что была большая переписка по этому поводу, но за ней не следил и была она давно.
Думал что с той поры что-то поменялось.
У себя я делал добавление через ХП, просто думал что с той поры что-то поменялось - вот и спросил.
Запрос SELECT ... для получения значения поля делается в другом scope из-за особенностей работы клары с таблицами, я так понимаю?
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Re: Автоинкрементные поля

Сообщение Денис »

Про то что нужно использовать именно значение SCOPE_IDENTITY() я знаю
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Identity

Сообщение Andrew™ »

Денис писал(а):Запрос SELECT ... для получения значения поля делается в другом scope из-за особенностей работы клары с таблицами, я так понимаю?
это не из за особенностей клары, уже вроде всё понятно
делай всё в одной ХП INSERT + получение IDENTITY
и возвращай в OUTPUT параметр
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Re: Identity

Сообщение Денис »

это не из за особенностей клары, уже вроде всё понятно
делай всё в одной ХП INSERT + получение IDENTITY
и возвращай в OUTPUT параметр
Это понятно. Скажи как с наименьшими телодвижениями сделать чтоб при добавлении записи вызывалась ХП у нужными параметрами и т.д.
Я делаю так: В шаблоне снимаю галку Incert, а в процедуре редактирования в класс ручками добавляю метод insert, в котором уже сам пишу то что мне нужно.[/quote]
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Identity

Сообщение Andrew™ »

Денис писал(а):
это не из за особенностей клары, уже вроде всё понятно
делай всё в одной ХП INSERT + получение IDENTITY
и возвращай в OUTPUT параметр
Это понятно. Скажи как с наименьшими телодвижениями сделать чтоб при добавлении записи вызывалась ХП у нужными параметрами и т.д.
Я делаю так: В шаблоне снимаю галку Incert, а в процедуре редактирования в класс ручками добавляю метод insert, в котором уже сам пишу то что мне нужно.
в шаблоне оставь всё как есть, просто OMIT на MAVINSERT поставь, хотя можно и как ты

как правильно и всегда правильно пробиндить все поля в ХП, т к имеют место быть OVER поля, то тут нужна определённая логика, которая заложена в библиотеке и которой можно воспользоваться.

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

в MAV:Save.Insert декларируешь 

tmp  MAVSelect
sql    MAVExecSP
   CODE
 tmp.BindFields(File)

  ! биндуем все поля записи продекоарированные в DCT
 loop i# = 1 to records(tmp.QCol)
   get(tmp.QCol,i#)
  DbFiles.Manager.QReadOnly.hField = tmp.QCol.AdrField
  GET(DbFiles.Manager.QReadOnly,DbFiles.Manager.QReadOnly.hField)
  IF ERRORCODE()
   sql.BindParameter(tmp.QCol.Field)
  END
 end
 ! биндуем OUTPUT доп параметр для получения нового ID первичного поля

  sql.BindParameter(File.IdentityField,SQL_PARAM_OUTPUT)

  IF sql.Run('myInsertToTable')
    MAVSHOWERROR
   RETURN 1
  END

  

  RETURN 0
ну и не забывай что за саму ХП на сервере ты отвечаешь сам
Денис
Бывалый
Сообщения: 70
Зарегистрирован: 07 Июль 2005, 5:39
Откуда: Хабаровск
Контактная информация:

Re: Identity

Сообщение Денис »

Ok. Затра попробую
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Identity

Сообщение Andrew™ »

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

можно попробовать ещё проще, без ХП но в одном скопе

в MAV:Save.Insert декларируешь 

str    MAVSTring
str2  MAVSTring 
tmp  MAVSelect 
sql    MAVExecSP 
   CODE 
 tmp.BindFields(File) 

  ! биндуем все поля записи продекоарированные в DCT 
 j# = 0
 loop i# = 1 to records(tmp.QCol) 
   get(tmp.QCol,i#) 
  DbFiles.Manager.QReadOnly.hField = tmp.QCol.AdrField 
  GET(DbFiles.Manager.QReadOnly,DbFiles.Manager.QReadOnly.hField) 
  IF ERRORCODE() 
   sql.BindParameter(tmp.QCol.Field) 
   str.AppendString(CHOOSE(j#=0,'',',') & '?')
   str2.AppendString(CHOOSE(j#=0,'',',') & tmp.Field(SELF.QCol.Field))
   j# += 1
  END 
 end 
 ! биндуем OUTPUT доп параметр для получения нового ID первичного поля 
   str.AppendString(CHOOSE(j#=0,'',',') & '?')

  sql.BindParameter(File.IdentityField,SQL_PARAM_OUTPUT) 

  IF sql.Run('BEGIN insert into ' & MAVTABLENAME(File) &|
   '(' & str2.S[1 : str2.Pos] & ') values(' & str.S[1 : str.Pos] & ') '  &|
     ?= SELECT SCOPE_IDENTITY() END'
    MAVSHOWERROR 
   RETURN 1 
  END 

  

  RETURN 0
Ответить