C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Как сохранить результат запроса
Guest
Отправлено: 14.05.2004, 12:17


Не зарегистрирован







Есть Query1 через который идет запрос к таблице. Результат выводится в DBGrid. Как то, что в этом гриде сохранить хоть во что-нить.(txt,xls,doc,...)?

DBGrid позволяет сортировать записи? Чтобы не использовать Order by?
Guest
Отправлено: 14.05.2004, 12:55


Не зарегистрирован







DBGrid не позволяет сортировать записи — не его задача. DBGrid только показывает результаты выборки. Order by на SQL'евских базах самый эффективный способ сортировки, так как использует внутренние возможности сервера.

Чтобы слить DBGrid ->DataSource->DataSet во внешний файл надо поработать ручками. Проще всего в текстовый файл с фиксированными разделителями — его понимает Excel
CODE

if (!DBGid? || ! DBGid?->DataSource) return;
TdataSet *ds = DBGid?->DataSource->DataSet;
if (!ds || !ds->Active) return;
ds->DisableControls();
for (ds->First(); !ds->Eof; ds->Next())
{
конкатенация всех полей кроме Memo,Blob и иже с ними AsString
запись полученной строки в файл
}
ds->EnableControls();

Я пользуюсь этим методом для экспорта в текст или Excel. Работает в сотни раз быстрее чем через COM сервер Excel’а.
Для экспорта в dbf некоторое время юзал ADO, но начались проблемы с настройкой и работоспособностью на разных машина — пришлось написать свой код для записи и чтения dbf файла. Вместо ADO можно использовать BDE у него есть интерпретатор SQL для разных форматов. Я стараюсь не использовать BDE — проблемы с настройкой при массовом тиражировании.
Удачи!
DVD
Отправлено: 17.05.2004, 09:03


Дежурный стрелочник

Группа: Участник
Сообщений: 33



А, как сортировать по вычисляемому полю, созданному средствами Builder'a? Эти поля нельзя использовать в Order by. Поля, создаваемые в свойствах полей Query, вычисляемые в событии OnCalcField...
olegenty
Отправлено: 17.05.2004, 09:33


Ветеран

Группа: Модератор
Сообщений: 2412



вряд ли есть такие вычисляемые поля, значения которых невозможно вычислить в запросе. а вот запрос позволяет и ORDER BY сделать :-))
Gedeon
Отправлено: 17.05.2004, 10:12


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE (DVD @ 17/05/2004, 10:05)
А, как сортировать по вычисляемому полю, созданному средствами Builder'a? Эти поля нельзя использовать в Order by. Поля, создаваемые в свойствах полей Query, вычисляемые в событии OnCalcField...

Перекладывайте всю возможную работу с клиента на сервер. Вычисляйте поля там, и сортируйте соответственно.
DVD
Отправлено: 17.05.2004, 15:51


Дежурный стрелочник

Группа: Участник
Сообщений: 33



ОК. Объясню. Есть база данных телефонных номеров. Номера зашифрованы простой операцией xor 1 на каждую цифру. Как мне в sql запросе выводить реальные номера телефонов?
Gedeon
Отправлено: 17.05.2004, 15:57


Ветеран

Группа: Модератор
Сообщений: 1742



SQL
GO
SELECT a_int_value ^ b_int_value
FROM bitwise
olegenty
Отправлено: 17.05.2004, 15:57


Ветеран

Группа: Модератор
Сообщений: 2412



чё за сервер у тебя?
напиши UDF (user defined function), и используй....
Guest
Отправлено: 18.05.2004, 08:16


Не зарегистрирован







QUOTE
Есть база данных телефонных номеров. Номера зашифрованы

А зачем вообще что то шифровать? Сервера БД позволяют закрыть от пользователя любую часть информации путем грамотной расстановки прав и создания View'ов.
Дополнительные преобразования над полем на стороне клиента причиняют много головной боли — нет сортировок, нет отбора по условию, нельзя делать связи и т.д.
Шифрование оправдано только в случае если вы хотите что бы кроме вашего приложения с этой базой никто не работал.
Gedeon
Отправлено: 18.05.2004, 08:44


Ветеран

Группа: Модератор
Сообщений: 1742



Ну во первых хотелось бы действительно узнать че за сервер-то. Во вторых действительно зачем применять шифрование, если можно все закрыть на уровне сервера, а доступ кстати зарубить всем и давать его вообще только прриложению(SQL Server для других СУБД не знаю). Единственно шифрование применять только если хотите данные скрыть от админов, но зачем от них скрывать номера телефонов? Алгоритм шифрования достаточно прост и опытному человеку его достаточно просто расшифровать.
DVD
Отправлено: 19.05.2004, 08:41


Дежурный стрелочник

Группа: Участник
Сообщений: 33



Какой сервер? Да кто его знает, по крайней мере не я. У меня просто есть на диске файлы dbf содержащие телефонную базу данных. В этой базе поле TEL поксорено на 1. Мне нужно написать прогу для работы с этой БД, используя SQL. Если не сложно объясните, как делать UDF? Я в SQL кроме SELECT, почти больше ничего незнаю. Если есть у кого доки про SQL в Билдере дайте линк или скиньте на мыло. biggrin.gif
DVD
Отправлено: 19.05.2004, 08:44


Дежурный стрелочник

Группа: Участник
Сообщений: 33



QUOTE
SQL
GO
SELECT a_int_value ^ b_int_value
FROM bitwise


А тип поля TEL string, как мне поксорить каждый символ?
Gedeon
Отправлено: 19.05.2004, 09:07


Ветеран

Группа: Модератор
Сообщений: 1742



QUOTE
Какой сервер? Да кто его знает, по крайней мере не я.

Приехали, а как, батенька мы к нему подключались?
QUOTE

А тип поля TEL string, как мне поксорить каждый символ?

В SQLServer это работает, как там в твоей базе, понятия не имею.
SQL
DECLARE @Test VARCHAR(10)
DECLARE @Int INTEGER
SET @Int = 3
SET @Test = '2334567'
SELECT @Test^3,@Int^1
AVC
Отправлено: 19.05.2004, 09:13


Не зарегистрирован







Sorry. Речь шла только о SQL'евских серверах.
У вас не сервер а одиночный файл. В этом случае если не хотите иметь головной боли с шифорваной информацией — создайте новый файл (програмно) где это поле будет дешифровано и работайте с ним. На него можно понасоздавать разные индексы. Одиночную dbf таблицу удобнее юзать не через SQL а через компонент TTable.

Или вариант №2 — загнать эту таблицу на какой либо SQL'евский сервер, можно караманный типа IB, SybaseASA6/7, MaxDB(SupDB) и т.д. При использовании любого сервера будет больше хлопот по его обслуживанию, но можно будет пользоваться преимуществами SQL.

Ещё живой вариант — перегнать таблицу в MySql, а интерфейс писать на html
Выбор варианта зависит от назначения приложения.
DVD
Отправлено: 19.05.2004, 15:28


Дежурный стрелочник

Группа: Участник
Сообщений: 33



Так. А какими средствами можно сделать новый файл, в котором уже будет все поксорено? Я создаю вычисляемое поле. Нужный вид таблицы отображается в DBgreed. Вот. Как бы теперь этот грид сохранить в новый файл. То, как описано в начале, мне не очень понятно. Может кто даст рабочий вариант? Мне надо-то раз перегнать. Эх, а так бы я из адреса сделал поля для улицы, дома и квартиры. cool.gif

Отредактировано DVD — 20/05/2004, 00:31
AVC
Отправлено: 19.05.2004, 16:11


Ветеран

Группа: Модератор
Сообщений: 1583



Самый простой вариант:
1.Любым доступным средством типа DBed, DBU, Fox и т.д. на худой конец можно попробовать dbd из комплекта Bielder'а создаем в dbf дополнительные поля.
2.Открываем файл в проекте компонентом TTable.
3.Проходим по всем записям заполняя новые поля значениями.
4.Закрываем и тем же чем добавляли удаляем старые поля.
DVD
Отправлено: 21.05.2004, 06:20


Дежурный стрелочник

Группа: Участник
Сообщений: 33



Ок. Так сработало. А как, все таки, сохранять результаты запросов в файлы. Пробовал BatchMove, но он позволяет сохранять в форматы баз данных. А если мне xls,txt форматы нужны?
olegenty
Отправлено: 21.05.2004, 07:15


Ветеран

Группа: Модератор
Сообщений: 2412



QUOTE

А если мне xls,txt форматы нужны?

то
1. Напишешь руками. Это не сложно.
2. Воспользуешься, например, FastReport, он это позволяет...
AVC
Отправлено: 21.05.2004, 07:40


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE
. А если мне xls,txt форматы нужны?

См. ответ гостя в начале темы.
DVD
Отправлено: 21.05.2004, 09:34


Дежурный стрелочник

Группа: Участник
Сообщений: 33



То, что в начале написано я читал. Я не знаю, как сохранять в текстовом формате ohmy.gif . Напишите рабочий вариант, пожалуйста.(тело цикла)

Отредактировано DVD — 21/05/2004, 18:40
AVC
Отправлено: 21.05.2004, 10:14


Ветеран

Группа: Модератор
Сообщений: 1583



CODE

void __fastcall TForm1::Button4Click(TObject *Sender)
{
if (!DBGrid1 || ! DBGrid1->DataSource) return;
TDataSet *ds = DBGrid1->DataSource->DataSet;
if (!ds || !ds->Active) return;

FILE *fout = fopen("aaa.txt", "wb");
if (!fout) return;
try {

AnsiString rec;          // буфер
AnsiString cdm = "\t";   // разделитель колонок
AnsiString rdm = "\r\n"; // разделитель срок
AnsiString str;

// Считаем что Memo,Blob и иже с ними в ds нет
rec = ""; // Title
for (int i=0; i < ds->FieldCount; i++)
{  str = ds->Fields->Fields[i]->DisplayName;
   if(str.IsEmpty()) str = ds->Fields->Fields[i]->FieldName;
   if (i) rec += cdm;
   rec += str;
}
rec += rdm;
fwrite(rec.c_str(), rec.Length(), 1, fout);

ds->DisableControls();
for (ds->First(); !ds->Eof; ds->Next())
{  rec = "";
   for (int i=0; i < ds->FieldCount; i++)
    {  try { str = ds->Fields->Fields[i]->AsString; }
       catch(...) { str = ""; }
       if (i) rec += cdm;
       rec += str;
    } // ds->FieldCount

   rec += rdm;
   fwrite(rec.c_str(), rec.Length(), 1, fout);
} // !ds->Eof

ds->EnableControls();
} // try fopen
catch (...) { fclose(fout); throw; }
fclose(fout);
}


Вернуться в Вопросы программирования в C++Builder