Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.012 c
2-1140881753
13
2006-02-25 18:35
2006.03.12
иконки в DLL


4-1135083663
morik
2005-12-20 16:01
2006.03.12
SendMessage и Double


5-1126858582
newGuest
2005-09-16 12:16
2006.03.12
Control has no parent window.


1-1138704330
Counter Terranist
2006-01-31 13:45
2006.03.12
PageControl.TabPosition в ХР


1-1139472708
DimaBr
2006-02-09 11:11
2006.03.12
Список компонентов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский