Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.12;
Скачать: CL | DM;

Вниз

Null в строке   Найти похожие ветки 

 
AndreyAR   (2006-01-18 09:03) [0]

Всем доброго времени суток.

Проблема в следующем: в строковом поле забиты строчки с символом #0. При попытке взять значение AsString возвращается пустая строка (размер 0), если же брать AsVariant, размер ненулевой. Как преобразовать Variant в String, заменив #0, например, пробелами, сохранив остальные символы?

Заранее спасибо всем, кто ответит.


 
Johnmen ©   (2006-01-18 09:10) [1]

Что за БД?


 
AndreyAR   (2006-01-18 09:22) [2]

БД "замечательная".

Pervasive SQL 2000i (раньше называлась Btrieve). Тип поля - Variable length note (240). Использую связку ADO + Merant ODBC Driver for Btrieve.

Ну дело в общем-то не в БД, может, даже и не в этот форум надо было писать :). Как Variant поле берется, вопрос как потом преобразовать в стринг.

Я у себя написал:

var asd: variant;
    s1: string;
...
asd:=fieldbyname("f_note").AsVariant;
s1:=VarToStr(asd);
showmessage(inttostr(length(s1))+"   "+inttostr(sizeof(asd)));

Выдается 0  16, т.е. вариант размером 16, преобразованный в стринг - 0. Причем доподлинно известно, что первый символ в строке #0.


 
Johnmen ©   (2006-01-18 09:29) [3]

Т.е. я правильно понял, что нужно получить строковое значение независимо от содержимого?
Если да, то как ты себе представляешь признак конца содержимого поля типа varchar ?


 
AndreyAR   (2006-01-18 09:37) [4]


> Если да, то как ты себе представляешь признак конца содержимого
> поля типа varchar ?


Ну, во-первых, не совсем varchar. И ODBC его нормально возвращает (прога на Fox Pro например прекрасно работает, с тем же драйвером).

Во-вторых вопрос в другом. Как преобразовать переменную Variant в string, заменив #0 на #32. Т.е. при преобразовании Variant получается скажем набор байтов 00 32 45 65. Надо сделать 32 32 45 65?


 
evvcom ©   (2006-01-18 09:38) [5]


> inttostr(sizeof(asd)));
> т.е. вариант размером 16

А кто тебе сказал, что SizeOf - это длина строки в варианте? Правильно, это размер, который занимает сама переменная типа Variant, но не строка.


 
AndreyAR   (2006-01-18 09:46) [6]


> А кто тебе сказал, что SizeOf - это длина строки в варианте?
>  Правильно, это размер, который занимает сама переменная
> типа Variant, но не строка.


Я уже догадался, но тем не менее факт остается фактом. Вообще, смысл моей программы в следующем: выгрузить таблицу из Btrieve в MS SQL. Сейчас работает подобная выгрузка в My Sql (там крутится FoxPro-шная прога). И значения этого самого поля в MySql выглядят так:

00 00 00 00 00 СF C5 D0 C5 C2 CE C4 (Hex-редактор)
|||||Перевод (а это сам текст).
Как видите, первые символы - нули :(


 
evvcom ©   (2006-01-18 09:49) [7]


> Как видите, первые символы - нули :(

Ну и? Что не нравится? Строка пустая. А после первого нуля (или 2, наверное, если unicode) дальше мусор. Тебе мусор что ли нужен?


 
Johnmen ©   (2006-01-18 09:53) [8]

A variant occupies 16 bytes of memory and consists of a type code and a value, or pointer to a value, of the type specified by the code. (с) Variant+F1

Преобразование из варианта в строку у тебя правильно, VarToStr.


 
AndreyAR   (2006-01-18 09:54) [9]


> Ну и? Что не нравится? Строка пустая. А после первого нуля
> (или 2, наверное, если unicode) дальше мусор. Тебе мусор
> что ли нужен?


Не мусор, а значение поля. Всего поле в Btrieve занимает 240 байт, то бишь 240 символов. Первые символы забиты нулями, а дальше идет текст - это такое внутреннее представление данных в этой долбаной СУБД - она же древняя, старше и Windows и меня наверно. Вот этот текст (после нулей) и нужен, это и есть значение поля.


 
AndreyAR   (2006-01-18 09:57) [10]

Тут пришла в голову мысль, что, может быть, ODBC возвращает значение с нулями, а вот ADO уже может и обрезать его?  Как полагаете?

Если так, то придется переписывать все вообще без sql через Pervasive API, а это такой геморрой...


 
Johnmen ©   (2006-01-18 09:59) [11]

Попробуй так
TBlobField(FieldByName("yourfield")).SaveTo....


 
AndreyAR   (2006-01-18 10:08) [12]


> Попробуй так
> TBlobField(FieldByName("yourfield")).SaveTo....


Сейчас попробую. Кстати, если SaveToStream, то какой Stream создавать? И как из него потом вытащить данные? Я со stream-ами просто не работал, а рыться в справке некогда.


 
Johnmen ©   (2006-01-18 10:12) [13]

http://delphimaster.net/view/3-1137401302/


 
evvcom ©   (2006-01-18 10:19) [14]


> Всего поле в Btrieve занимает 240 байт, то бишь 240 символов.
> Тип поля - Variable length note (240).

Я, конечно, с Btrieve не знаком, но "Variable length note (240)" мне говорит о том, что поле это переменной длины и 240 - это максимум символов, которые может хранить это поле.

> Тут пришла в голову мысль, что, может быть, ODBC возвращает
> значение с нулями, а вот ADO уже может и обрезать его?  
> Как полагаете?

ODBC и ADO писаны одним разработчиком (компанией, насколько мне известно :)), поэтому нестыковки между ними скорее всего сведены к минимуму :) (хотя, конечно, всякое бывает). Главное здесь делает провайдер, он знает все особенности и тонкости работы с сервером. Если провайдер установлен верно, и у Btrieve действительно есть такая особенность хранения строк, то провайдер это должен учесть и пустить строку далее в стандартном, понимаемом его клиентами виде.
Ты уверен, что там действительно есть эти данные? Родные инструменты работы с СУБД это подтверждают?


 
AndreyAR   (2006-01-18 10:44) [15]


> Ты уверен, что там действительно есть эти данные? Родные
> инструменты работы с СУБД это подтверждают?


Данные из этого поля - назначение платежа из балансовых проводок АБС "Диасофт Кард", кто знает.
Если бы их там не было, нам бы всем головы снесли давно :)). Ну и выгрузка FoxPro-шной прогой в MySQL это подтверждает. Драйвер, кстати, может быть не рассчитан на работу с ADO, хотя х.з., сейчас проверю вариант Joinmen-a.

А как, кстати, взять потом данные из Stream-a? Я например сделаю

var ss: tmemorystream;
...
TBlobField(FieldByName("yourfield")).SaveToStream(ss);

а что потом?


 
Виталий Панасенко   (2006-01-18 10:49) [16]

Чего-то я не догняю.. Null он же и в Африке Null... Похоже, автор сам себе(и остальным) придумал заморочку на голом месте.. Либо ODBC драйвер глюкавит...А в поле действительно что-то есть ?


 
AndreyAR   (2006-01-18 10:52) [17]


> А в поле действительно что-то есть ?

Есть, есть, не сомневайтесь :)).
Null в смысле символ с ASCII-кодом 0. СУБД писалась задолго до появления винды, а там такое возможно.


 
Johnmen ©   (2006-01-18 10:56) [18]

var s : string;
...
SetLength(s,ss.Size);

Move(ss.Memory,s[1],ss.Size);
или
ss.Position:=0;
ss.ReadBuffer(s[1],ss.Size);


 
sniknik ©   (2006-01-18 11:00) [19]

AndreyAR   (18.01.06 09:46) [6]
> Вообще, смысл моей программы в следующем: выгрузить таблицу из Btrieve в MS SQL.
DTS
гетерогенные запросы в самом MSSQL

evvcom ©   (18.01.06 10:19) [14]
> поэтому нестыковки между ними скорее всего сведены к минимуму :)
я бы сказал больше. там вообше один и тот же код там где это позволяется... т.е. пишут в OLEDB (ADO), а в драйвере ODBC "пустышки" с вызовами OLEDB аналогов...
имхо естественно. (я бы так сделал, если бы "тянул" 2 драйвера сразу)

p.s. varbinary представленный строкой может и не такие "чудеса" выдать... ;о)


 
evvcom ©   (2006-01-18 11:05) [20]


> а что потом?

1. Сбросить позицию. ss.Position := 0;
2. TStream + F1, например, ss.ReadBuffer


 
AndreyAR   (2006-01-18 11:13) [21]


> DTS
> гетерогенные запросы в самом MSSQL


К сожалению, не прокатит - таблицы не совпадают по структуре: например, есть пустые поля, которые нафиг не нужно выгружать. Кроме того, нужно конвертировать дату/время (Btrieve хранит дату в формату клариона).
Ну и последний момент - выгрузка должна происходить ежедневно, для обеспечения актуальности данных. По совокупности причин проще написать свой маленький конвертер.


 
sniknik ©   (2006-01-18 11:24) [22]

> К сожалению, не прокатит - таблицы не совпадают по структуре:...
ну так ты хотябы раз проверь, закачай табличку то... правильно перенес? а тип поля какой создал?...

> По совокупности причин проще написать свой маленький конвертер.
пока приведены не причины, а отмазки, и конвертацию и преобразования можно/и лучше в самом запросе и сделать. а то что это будет работать быстрее любого твоего самописного конвертера как раз веский аргумент за запрос... тем более  "выгрузка должна происходить ежедневно".


 
AndreyAR   (2006-01-18 11:35) [23]

Уважаемый, "табличка" весит 4 Гб. И грузится она частями специальным конвертером. Т.е. ночью выгружаются проводки, которые были добавлены днем. Дата, за которую грузить, выбирается из другой таблицы (закрытых опер. дней) и т.д. Задача не самая простая и "в лоб" одним запросом её не решить.

А на самом деле быстро будет (DTS и рядом не стоял), когда выгрузка будет переписана на использование Pervasive API, поскольку Merant ODBC Driver - тормоз по определению.


 
Плохиш ©   (2006-01-18 11:41) [24]


> AndreyAR   (18.01.06 11:35) [23]

Пора бы про строки нулём заканчивающиеся почитать.
У тебё в поле хранится не строка а набор байт(символов) (в терминах делфи это называется динамический массив, про них то же пора бы почитать), вот и обрабатывай как массив символов.
За определённую оплату я готов сделать эту работу за тебя, но учти, что час моей работы стоит 30 Евро + налоги + непредвиденные расходы.


 
sniknik ©   (2006-01-18 11:44) [25]

AndreyAR   (18.01.06 11:35) [23]
понятно...
действительно понятно, операторы TOP xxx, ограничения по WHERE xxx автору пожоже неизвестны... и пишет он похоже используя рабочую базу...

чтож, не будем мешать, флаг тебе в руки.


 
Johnmen ©   (2006-01-18 11:46) [26]

+ соцпакет + трёхразовый харч + медстрах полис кремлёвки
:)))


 
Виталий Панасенко   (2006-01-18 11:47) [27]


> AndreyAR   (18.01.06 10:52) [17]
>
> > А в поле действительно что-то есть ?
>
> Есть, есть, не сомневайтесь :)).
> Null в смысле символ с ASCII-кодом 0. СУБД писалась задолго
> до появления винды, а там такое возможно.

А при чем тут Винда ? задолго до Винды были Unix, NetWare.. И почему не допускается такой вариант, что уже тогда было понятие "пусто"("не определено" точнее)? А то, как это значение реализовано.. В Paradox для Numeric/Currency полей используется специальное значение Double - NAN (Not A Numeric), для Short - -32768, Long Integer/Date - -2147483648, строка - "". и все это при просмотре в HEX будет отображаться соответсвующими байтами(а Short/LongInt/Date вообще обычное число, отрицательное)...Так что, да там что-то есть.. Но это "что-то" сигнализирует системе(СУБД) "ЗНАЧЕНИЕ НЕ ОПРЕДЕЛЕНО" (Null)


 
Плохиш ©   (2006-01-18 11:54) [28]


> Johnmen ©   (18.01.06 11:46) [26]
> + соцпакет + трёхразовый харч + медстрах полис кремлёвки
> :)))

С выездом, транспортные расходы + суточные входят в непредвиденные расходы.
А за напоминае про страховки спасибо :-)


 
AndreyAR   (2006-01-18 11:57) [29]


> Пора бы про строки нулём заканчивающиеся почитать.
> У тебё в поле хранится не строка а набор байт(символов)
> (в терминах делфи это называется динамический массив, про
> них то же пора бы почитать), вот и обрабатывай как массив
> символов.
> За определённую оплату я готов сделать эту работу за тебя,
>  но учти, что час моей работы стоит 30 Евро + налоги + непредвиденные
> расходы.

если раскажешь, как заполнить массив байтами из этого поля, я тебе перешлю 30 Евро. Серьезно.

Пока что на
TBlobField(FieldByName("f_note")).SaveToFile("c:\str.txt");
пишет "Invalid Typecast".


 
AndreyAR   (2006-01-18 12:00) [30]


> понятно...
> действительно понятно, операторы TOP xxx, ограничения по
> WHERE xxx автору пожоже неизвестны... и пишет он похоже
> используя рабочую базу...


Ну конечно неизвестны, в нашей церковно-приходской школе о таком не упоминали!

> чтож, не будем мешать, флаг тебе в руки.
Всего Вам.


 
Виталий Панасенко   (2006-01-18 12:07) [31]

выбери из таблицы записи, у которых это занятное поле IS NULL (select * from table_name where field is null) и глянь, а не попала ли туда, случайно, запись, которую ты сейчас обсуждаешь.. Если да, то ...


 
AndreyAR   (2006-01-18 12:18) [32]


> выбери из таблицы записи, у которых это занятное поле IS
> NULL (select * from table_name where field is null) и глянь,
>  а не попала ли туда, случайно, запись, которую ты сейчас
> обсуждаешь.. Если да, то ...


Делать такой селект достаточно долго, таблица большая (это во-первых), во-вторых, where нормально отрабатывает (с приемлимой скоростью), если я точно попадаю в индексы Btriev-a (т.е. в where входят все поля, указанные в индексе).


 
Johnmen ©   (2006-01-18 12:20) [33]

Пробуй TBinaryField, TBytesField...


 
Виталий Панасенко   (2006-01-18 12:51) [34]


> Johnmen ©   (18.01.06 12:20) [33]
> Пробуй TBinaryField, TBytesField...

А че пробовать ? В дизайнере полей создать поля и глянуть тип созданного поля


 
Плохиш ©   (2006-01-18 13:14) [35]


> AndreyAR   (18.01.06 11:57) [29]

var
 myVar: Variant;
 lCount: Integer;
 str: String;
begin
 myVar := FieldByName("f_note").Value;
 for lCount := 0 to sizeof(myVar) - 1 do
   if myVar[lCount] = 0 then myVar[lCount] := 32;
 str := myVar;
end;

Надеюсь идея понятна?


 
Плохиш ©   (2006-01-18 13:17) [36]

А ещё лучше прочитать про метод GetData класса TField?


 
AndreyAR   (2006-01-18 13:26) [37]


> Пробуй TBinaryField, TBytesField...


Не хочу уже. Сделал выборку с использованием API первазива - все просто "летает".

Остальным "мастерам" спасибо за "помощь". :))


 
AndreyAR   (2006-01-18 13:29) [38]


> Надеюсь идея понятна?


интересная идея, жаль, не пригодится :)


 
Johnmen ©   (2006-01-18 13:35) [39]

>Плохиш ©   (18.01.06 13:14) [35]

Иде я?
Идея не пройдёт...:)
Т.к. ключевые моменты (sizeof(myVar), myVar[lCount]) не "соотносятся" с действительностью..


 
Плохиш ©   (2006-01-18 13:40) [40]


> Johnmen ©   (18.01.06 13:35) [39]

:-) да мне по фиг, да и автору я смотрю тоже.
Отправил пост и вспомнил про GetData.



Страницы: 1 2 вся ветка

Текущий архив: 2006.03.12;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.035 c
15-1140202527
Shastox
2006-02-17 21:55
2006.03.12
Мысль о процессах


2-1140689661
Михаил (Киров)
2006-02-23 13:14
2006.03.12
Данные в exe


2-1140894183
Wel
2006-02-25 22:03
2006.03.12
Как загрузить из ImageList


4-1134982464
Chaser
2005-12-19 11:54
2006.03.12
При закрытии программы - минимизация в трей


15-1140187686
kaZaNoVa
2006-02-17 17:48
2006.03.12
Мониторинг и анализ передаваемой Браузером информации