Страница 11 из 12

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

Добавлено: 26 Февраль 2006, 9:33
Andrew™
Новый режим добавлен в конструктор фильтров - FREE LIKE, что означает что введённая конструкция подставляется в LIKE ? as is, единственно введён контроль на длину ввода , если введённое значение больше размера поля в БД по которому производится поиск, введённое значение обрезается до размера поля в БД и вместо LIKE в WHERE конструкцию попадёт обычное сравнение Field=?, иначе просто будет ошибка биндования.

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

Добавлено: 26 Февраль 2006, 15:57
Andrew™
неоднократно меня спрашивали - а есть ли шаблон который контролирует количество одновременно запущенных оконных процедур в программе, с целью запрета запуска определённого количеста таких процедур и активацией уже открытого окна

я всё отмахивался, наверняка что то похожее есть и в ABCFree, зачем спрашивается изобретать велосипед. А вот сегодня разродится и сделал. ;)

MAVSelect

Добавлено: 28 Февраль 2006, 15:28
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 запись, и нет смысла держать откытым ресурс


библиотека подрихтована на тему если заказали определённое количество записей и читаем последнюю (ошибки нет, т к по ошибке происходит закрытие) закрываем принудительно курсор

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

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

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

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

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

Добавлено: 06 Март 2006, 10:59
Денис
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% нужно заводить для добавления ХП ? Или как ?

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

Добавлено: 06 Март 2006, 11:25
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 может быть изменено
из другой сессии.

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

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

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

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

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

с моей точки зрения IDENTITY это средство для ленивых, уж если ребятки введи такую возможность почему в той же самой доке по серваку напЫсано что в определённых задачах нельзя использовать IDENTITY механизмов.

Identity

Добавлено: 06 Март 2006, 14:22
Денис
По поводу примера, что ты привел. Его я не видел на форуме, так как вопросы разбросаны черте как по форуму. Я знаю что была большая переписка по этому поводу, но за ней не следил и была она давно.
Думал что с той поры что-то поменялось.
У себя я делал добавление через ХП, просто думал что с той поры что-то поменялось - вот и спросил.
Запрос SELECT ... для получения значения поля делается в другом scope из-за особенностей работы клары с таблицами, я так понимаю?

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

Добавлено: 06 Март 2006, 14:24
Денис
Про то что нужно использовать именно значение SCOPE_IDENTITY() я знаю

Re: Identity

Добавлено: 06 Март 2006, 14:34
Andrew™
Денис писал(а):Запрос SELECT ... для получения значения поля делается в другом scope из-за особенностей работы клары с таблицами, я так понимаю?
это не из за особенностей клары, уже вроде всё понятно
делай всё в одной ХП INSERT + получение IDENTITY
и возвращай в OUTPUT параметр

Re: Identity

Добавлено: 06 Март 2006, 14:49
Денис
это не из за особенностей клары, уже вроде всё понятно
делай всё в одной ХП INSERT + получение IDENTITY
и возвращай в OUTPUT параметр
Это понятно. Скажи как с наименьшими телодвижениями сделать чтоб при добавлении записи вызывалась ХП у нужными параметрами и т.д.
Я делаю так: В шаблоне снимаю галку Incert, а в процедуре редактирования в класс ручками добавляю метод insert, в котором уже сам пишу то что мне нужно.[/quote]

Re: Identity

Добавлено: 06 Март 2006, 15:00
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
ну и не забывай что за саму ХП на сервере ты отвечаешь сам

Re: Identity

Добавлено: 06 Март 2006, 15:16
Денис
Ok. Затра попробую

Re: Identity

Добавлено: 06 Март 2006, 15:17
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