Форум: "Базы";
Текущий архив: 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.55 MB
Время: 0.014 c