Как с помощью SQL извлечь структуру из CtgVal.value ?
0 (0)
Как с помощью SQL извлечь структуру из CtgVal.value ? ( DmitriyG 15.07.2009 15:33 )
5(1)Здравствуйте!
В тех случаях, когда в CtgVal.value хранится сложная структура, например, для ctgId=308 (характеристика операций):AttrID LONG 4 Идентификатор значения Reserve CHR 96 Резерв Value STRING 1400 Строковое значение
как её можно прочитать с помощью SQL-запроса? Так не удаётся:SELECT CONVERT(object,SQL_INTEGER) AS client, CAST(value AS BINARY) AS binVal FROM CtgVal_dbt WHERE (objectType=3) AND (ctgId=308)
При этом во всех полученных записях, в поле binVal оказывается одно и то же: 0x23, 0x0A, и дальше только нули. Очевидно, это AttrID, т.е. начало структуры, хранящейся в value.
Через интерфейс RS-bank я вижу, что у этих клиентов там ещё должен быть текст, например "розничная торговля отделочными материалами" и т.п. Но SQL, похоже, считывает из поля value данные лишь до первого встреченного двоичного нуля, принимая его за конец строки. CAST(SUBSTRING(value,101,100) AS BINARY) тоже не помогает...
Как же мне извлечь остальное содержимое из CtgVal.value ?
>> ОтветитьRe ( utkin 15.09.2009 17:38 )
5(1)Некро-привет,
Для категории 308 и подобных ей, на строку таблицы ctgval.dbt накладывается структура, в которой поле Value имеет тип Long. Соответственно, я создал отдельный пользовательский словарь и добавил в него файл ctgval2.dbt, в котором структура такая же как в ctgval.dbt, но вместо Value String 1500 сделал Value Long и ValueTemp String 1496. Потом это всё доконвертировал в .ddf, и обращаюсь к ctgval2_dbt, когда мне этого надо.
>> ОтветитьО чудо!, неужели кто-то ответил!!! ( Outcast 15.09.2009 18:46 )
5(1)Давно задавал такой вопрос в теме
А как с помощью SQL наложить структуру ctgval2.dbt на файл ctgval.dbt? самих записей в таблице ctgval2.dbt не существует, они в ctgval.dbt
>> ОтветитьRe Re ( DmitriyG 16.09.2009 09:43 )
5(1)Спасибо за ответ! (Я тоже уже было решил, что этот форум мёртвый).
Суть метода так сходу не очень понял, постараюсь разобраться.
Например, как появляются данные в пользовательской ctgval2_dbt? Ведь система сохраняет их в свою ctgval_dbt. Допустим, мы через ODBC обратимся к нашей ctgval2_dbt, чтобы "подхватилось" нужное нам описание структуы для поля value, но тогда он и данные попытается извлечь тоже из нашей ctgval2_dbt, а не из родной ОДБ-шной ctgval_dbt. Правильно я понимаю? Или в Первасиве можно настроить некую внутреннюю переадресацию, чтобы описание данных бралось из ctgval2, а данные из ctgval ?
>> ОтветитьГрандиозная афёра ( utkin 16.09.2009 11:24 )
5(1)Пардон, я всех обманул. На самом деле ничего это не работает. Метод был теоретический. Посыпаю голову пеплом.
Реально дело обстоит по-другому: есть отдельный словарь, и таблица в нём называется ctgval.dbt, а не ctgval2.dbt, то есть наша структура накладывается на существующий файл. Структура - описанная мной выше. Для этого словаря сделаны .ddf, и положены в отдельную папку. Создана отдельная БД в ODBC, для которой путь к словарю - это путь к этой папке, а путь к таблицам - это путь к DBFile. Через SQL всё это выбирается отдельным подключением, через вновь созданную БД.
>> ОтветитьА вообще-то не настолько грандиозна эта афера!!! Все можно сделать если поковыряться... ( Ilya 21.12.2009 16:27 )
5(1)1. Сперва надо научиться видеть через RSL значение, которое мы хотим увидеть в SQL
Для этого, например, копируем ctgval.dbt в файл с другим именем (например ctgval1.dbt) и копируем структуру ctgval.dbt в какой-либо пользовательский словарь с аналогичным именем ctgval1.dbt .
Методом проб и ошибок заменяем поле Value String(1500) набором полей, которые позволят увидеть значение категории. например для типа значения категории "Целое" надо выделить Value_0 LONG(4) и Value_1 STRING(1496).
Итак мы получили структуру, которая умеет "видеть" значение категории типа "Целое"
2. Дополняем DDF-ку новой структурой
К сожалению штатный RSL-ий конвертер в DDF работает не корректно, поэтому:
- берем пустые DDF-ки (например здесь http://www.limanworld.ru/rs/files/clear_ddf_8.rar)
- кладем их в TXTFILE
- входим в оболочку RSL и выполняем дозапись в DDF из словаря bank.def
- теперь открываем пользовательский словарь со структурой ctgval1.dbt и выполняем дозапись в DDF из него
- копируем DDF-ки в DBFILE
3. Корректировка имени файла для структуры ctgval1.dbt в DDF-ке
Для каждой структуры в DDF существует свойство Location, которое определяет к какому физическом файлу будет применяться структура.
Проще всего это сделать с помощью утилиты DDFEdit или подобной. У кого таковой нет - можно написать макрос. Если кому интересно, секретом написания макроса поделюсь в следующих постах.
После всех манипуляций мы имеем возможность написать SQL-запрос, например такой
SELECT * from ctgval1_dbt where CtgID = 517
и в колонке Value_0 получить числовые значения для категории...
>> ОтветитьLocation ( Outcast 21.12.2009 17:02 )
5(1)Конечно очень интересно как поправить ddf, тем более макросом.
Поделитесь, пожалуйста. Спасибо!
>> ОтветитьПример макроса по ссылке... ( Ilya 21.12.2009 17:55 )
5(1)тут http://www.limanworld.ru/rs/files/ddf_ch_loc.rar
В архиве макрос и словарь с описанием структур DDF.
По умолчанию настроен, что корректируемые DDF-ки должны лежать вместе с макросом в папке ..\DBFILE\DDF
После этого не забыть переложить их в DBFILE
>> ОтветитьDDF.DEF ( Outcast 21.12.2009 18:50 )
5(1)Большое человеческое СПАСИБО!
Скорее даже не за макрос, а за словарь. Интересно как узнали структуру? Может знаете структуру BTRMAC.DDF, а то поддержка раскрывать секреты отказалась...
и зачем в макросе посимвольно достаем имя с наложением SetRecordAddr(r, f, 0, i+2, true);
можно и сразу достать f.Name?
>> ОтветитьНемножко по другому хранятся поля в DDF ( Ilya 21.12.2009 20:14 )
5(1)Поля Name и Location в отличие от RSL-их строк не являются Z-строками (т.е. заканчивающимися на #00). Это как в DBF строки заданной длинны добитые пробелами. Поэтому при считывании f.Name мы получаем длинную строку в которой увидем и Name и Location и другую фигню... пока не встретится #00. Т.е. Name это не VARCHAR(20), а скорее CHAR(20).
Поэтому корректнее так. Правильнее было бы просто считать посимвольно 20 байт, слепить из них строку и потом сделать trim(). Да и присвоение f.Location = pNewLoc, тоже не совсем корректно, так как мы туда записываем Z-строку. Главное, что Pervasive проглатывает и так.
А расковыривание струтуры DDF.DEF, дело рук небезызвестного sokols. Так что ему тоже респект.
А brtmac.ddf можно будет посмотреть... если время будет...
>> ОтветитьПеределал DDF.DEF ( Ilya 22.12.2009 11:41 )
5(1)добавил остальные DDF-структуры и немножко причесал сегменты ключей
http://www.limanworld.ru/rs/files/ddf_def_091222.rar
>> Ответитьbtrmac.ddf (+) ( sokols 23.12.2009 12:20 )
5(1)Расковырял, пользоваться можно, хотя вопросы ещё остались. Ilya словарик с описанием структуры выложил рядышком с ddf.def, забирайте: http://www.limanworld.ru/rs/files/btrmac_def.rar
Коротко поясню то, что может быть непонятно:
Part - номер части макроса. Если макрос длиннее МДПЧ (здесь - 4096), он, очевидно, будет разбит. Чтобы его прочитать, надо читать переменные части с заданным MacroName по порядку возрастания поля Part.
Length - почти понятно. Слегка не соответствует длине макроса. Кто разберётся - уточните, плиз.
CRC - не уверен, но, скорее всего, CRC и есть. Мог наврать, хотя это было бы логично.
Dir - номер директории, описанной в файле BM_DIR.DBT. Если это не первая часть макроса, то Dir=0.
Flags - не понял. Может, и не флаги, хотя значения уж больно хорошие получаются :-) Для макросов, введённых мною, получились флаги=15. Для не первой части макроса - снова 0.
Да. С этого надо было начинать, хотя все уже, конечно, поняли: текст макроса лежит в переменной части.
Удачи.
>> Ответить
Создание дублирующей структуры ( kapurov 23.12.2009 07:23 )
5(1)--Создание структуры
DROP TABLE ZZDBTCTGVAL IN DICTIONARY;
CREATE TABLE ZZDBTCTGVAL USING 'ctgval.dbt'
( ObjectType SMALLINT NOT NULL ,CtgID INTEGER NOT NULL ,ValueID INTEGER NOT NULL ,Sort SMALLINT NOT NULL
,Object VARCHAR(35) NOT NULL ,Value0 CHAR(100) NOT NULL
,Value1 CHAR(255) NOT NULL ,Value2 CHAR(255) NOT NULL
,Value3 CHAR(255) NOT NULL ,Value4 CHAR(255) NOT NULL
,Value5 CHAR(255) NOT NULL ,Value6 CHAR(125) NOT NULL
,signPrim CHAR(1) NOT NULL
,entDate DATE NOT NULL ,entTime TIME NOT NULL ,Oper SMALLINT NOT NULL ,startDate DATE NOT NULL
,endDate DATE NOT NULL
,NumSession INTEGER NOT NULL ,Reserve0 CHAR(255) NOT NULL ,Reserve1 CHAR(41) NOT NULL
);
-- Чтение объекта %p0% типа ctgId номер %p1%
SELECT TOP 1 k2.Value FROM ctgval_dbt k2 WHERE k2.OBJECT=Right('000000000'+Convert(%p0%,SQL_CHAR),10) And k2.CtgID=%p1%;
-- Чтение сложного объекта
SELECT v2.CodeList,v2.Name,k2.Value1 FROM zzdbtctgval k2,refval_dbt v2 WHERE k2.OBJECT=Right('000000000'+Convert(%p0%,SQL_CHAR),10)
And k2.CtgID=%p1% And v2.CtgID=k2.CtgID And v2.AttrID=
(( IF(ASCII(Substring(k2.Value0,2,1))<0,256,0)+ASCII(Substring(k2.Value0,2,1)) )*256
+( IF(ASCII(Substring(k2.Value0,1,1))<0,256,0)+ASCII(Substring(k2.Value0,1,1)) )*1);
>> ОтветитьДа-да! Мы же совсем забыли, что у нас есть SQL :-) ( BLIP 23.12.2009 09:22 )
5(1)Единственное, что смущает - обилие преобразований в "Чтении сложного объекта".
Интересно, насколько это сказывается на производительности?
>> Ответить