Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Delphi - получаем данные из Query

Автор: bartlinux
Дата сообщения: 14.11.2007 16:33
Вобщем, проблема.
Есть необходимость хранить в базе данных шифрованные значения. Это для того, чтобы базу нельзя было увести через просотй дамп базы.
База данных - MySQL.
Когда нам надо получить данные из этой таблицы, программа создаёт временную таблицу, и циклом копирует туда дешифрованные данные. После в делает новый запрос SELECT temp_tab и данные выводятся в грид.

Заполнение циклом работает примерно так:

Код:
zquery.open;
while not zquery.eof do begin
s:=s+'('+un_crp(zquery.fieldvalue['name'])+')';
zquery.next;
end;
ExecSQL('INSERT INTO temp_tabl VALUES ('+s+')');
Автор: eLLoco
Дата сообщения: 14.11.2007 19:45
bartlinux

Цитата:
Какие есть способы ускорить получения таблицы?

Если вся шифрация/дешифрация выполняется в клиентском приложении то, ИМХО, никак, поскольку записи извлекаются построчно. И чем больше будет таблица, тем медленней будет она дешифрироваться во временную. Не знаю о программных интерфейсах MySQL, в в MS SQL Server я бы запихал .NET сборку с криптофункциям в базу, чтобы не извлекать данные на клиента для обработки.

Но! Можно ведь реализовать программу таким образом, чтобы дешифрировались только запрашиваемые данные, а не вся таблица. Например, оставить несколько столбцов, входящих в нужный индекс, незашифрованными.
Автор: bartlinux
Дата сообщения: 14.11.2007 20:11
ну, если толко несколько столбцов сделать не зашифрованными - скорости это особо не прибавит...
Автор: eLLoco
Дата сообщения: 14.11.2007 21:16

Цитата:
ну, если толко несколько столбцов сделать не зашифрованными - скорости это особо не прибавит...

Не, ты не понял, если сделать нешифрованными столбцы индекса, нам вообще можно не формировать дешифрованную таблицу, либо формировать ее постепенно, по возникновении обращений к новым записям. Т.е. алгоритм такой - запрашиваем строки обычным запросом из ШИФРОВАННОЙ таблицы (индекс-то у нас в открытом виде), а в клиентском приложении расшифровываем полученную выборку. Все данные передаются набором, за один раз.

Этот метод не подойдет только в случае, когда выборка происходит по полям, которые обязательно нужно шифровать.
Автор: bartlinux
Дата сообщения: 14.11.2007 21:56
ты угадал, как раз нужно будет делать выборку по шифрованным полям...
Автор: eLLoco
Дата сообщения: 14.11.2007 22:22

Цитата:
2. while not zquery.eof (2 min)

Задетализируй профайлером, что здесь занимает основную часть времени - выборка строки из базы или же ее шифрование. Понятно, что во втором случае сделать ничего не получится, кроме как упростить алгоритм шифрования.
Автор: bartlinux
Дата сообщения: 14.11.2007 22:27
проверял. именно выборка из базы.
Автор: eLLoco
Дата сообщения: 14.11.2007 22:50
Напоследок, могу предложить копать в сторону (Query - MySQL) на предмет выборки всей совокупности данных / отмены отложенной выборки. Надо избавляться от построчного обращения к таблице. К сожалению, конкретных рекомендаций дать не смогу.
Автор: thetroll
Дата сообщения: 15.11.2007 03:20
Убится об стену! Почитайте про CDS (Client Data Set).

В 2-х словах - это компонент подменяющий Table, DataSet, Query. Выборка данных в ОЗУ, обработка, сохранение при необходимости. Может фильтровать выборку (Filter, Filtered). Может сортировать данные после выборки (создаем индексы).

После выборки (я правильно понимаю, что вытягивается вся база?), декодируем поля (все происходит в памяти), сортируем результат (создаем индексы), фильтруем (Filter) и подключаем Grid (EnableControls). Это займет миллисекунды.

Я бы предложил при выборке создать фиктивное поле, в котором хранить признак изменения строки (чтоб не сохранять все записи, а только измененные).

Я понятно выразился?
Автор: bartlinux
Дата сообщения: 15.11.2007 09:48
объясни, как получить данные в ClientDataSet из другого Query?
Автор: BaluBig
Дата сообщения: 15.11.2007 10:04
bartlinux
Для нормального современного компа LIKE-фильтрация 7000 записей - пустяки. Переноси её на клиента. При помощи Client Data Set или как угодно. Тут уже обсуждали похожую проблему, но, как я понимаю, у тебя нет возможности писать свои функции (UDF, user-defined function) для MySQL, как сделал тов. DroN_S из того топика. Потому что построчная обработка данных, да еще и вставка, убивают все преймущества от использования SQL-сервера.
Еще по поводу объема данных. Какого рода данные фильтруются? Думается мне, это какой-то справочник, который до бесконечности расти не будет, т.е. объемы данных, существенно отличающиеся от 7000 записей не ожидаются?
Автор: bartlinux
Дата сообщения: 15.11.2007 10:52
А кто обьяснит, почему при загрузки таблицы в ClientDataSet (таблицу получаем через провайдера от query), не обрабатывается значение OnCalcFields?
Автор: BaluBig
Дата сообщения: 15.11.2007 12:14
bartlinux

Цитата:
таблицу получаем через провайдера от query

Можно код увидеть? Потому что:

OnCalcFields is triggered when:
A dataset is opened.
A dataset is put into dsEdit state.
A record is retrieved from a database.
Автор: bartlinux
Дата сообщения: 15.11.2007 13:04
Вобщем, прикольная вешь ClientDataSet, вот только время refresh в 2 раза больше, чем если это сделать у Query... (при 7 000 записей, примерно 4 секунды)
Автор: bartlinux
Дата сообщения: 15.11.2007 22:27
А как заставить Query и ClientDataSet не запрашивать всю таблицу, а только обновленные строки?
Автор: BaluBig
Дата сообщения: 16.11.2007 12:51
bartlinux

Цитата:
А как заставить Query и ClientDataSet не запрашивать всю таблицу, а только обновленные строки?
Обновленные кем? Обновленные в данной сессии или обновленнные кем-то еще?
В первом случае нужно иметь отдельный запрос, который перечитает нужные записи (ты же знаешь, какие записи ты обновил) и обновит их в CDS.
Во втором случае - никак. Никакого понятия о том, какие строки изменились, оно не имеет. Этим занимается обычно сервер приложений. Как вариант можно попробовать сделать так: в записи организуется поле, хранящее дату-время последней модификации записи, за заполнение этого поля отвечает триггер (в MySQL есть триггеры?). Клиент должен запрашивать не все записи, а те, у которых время модификации больше времени последнего считывания записей на клиента.
Автор: bartlinux
Дата сообщения: 16.11.2007 13:00
Обновлять...
Удаляю я из одной таблицы, при этом надо, чтобы эта запись попала в другую таблицу. И потом обновляю обе... получается дофига времени. (делаю по сути 4 запроса)...
Автор: bartlinux
Дата сообщения: 27.01.2008 18:13
вобщем, пришлось отказаться от идеи хранить шифрованные данные в базе. CDS очень интересная штука, но при моем обьеме записей - обсалютно бесполезная вещь
-при открытии CDS - офигенно много времени занимет
-еще больше времени при обновлении
-кушает слишком много памяти.... при 7 000 записей - примерно 50 мб

А защита от слива решилась следующим образом:
-базу поставили на выделенный сервак
-сняли все пишушие устройства
-корпус и порты были опломбированы
-написал небольшой драйвер который запрещает копировать некоторые файлы.
Естественно, нету гарантии что сервер не унесут )
Автор: clear2121
Дата сообщения: 29.01.2008 04:51
bartlinux
А именно MySQL нужен? Если движок не критичен, то посмотри ADS. Там есть шифрация на уровне записи и/или таблицы. Очень быстрая. Я использовал в одном проекте связку MS SQL 2005 и ADS (для шифрации). Полностью поддерживает язык SQL, бесплатен.

Добавлено:
http://www.sybase.com/products/databasemanagement/advantagedatabaseserver

Добавлено:
А это сам компонент
http://www.sybase.com/products/databasemanagement/advantagedatabaseserver/tdataset-descendant

Добавлено:
А еще лучше
http://devzone.advantagedatabase.com/
Поищи Advantage Data Access Components (Delphi 8 and Greater / Turbo Pro Products)
Автор: Aquest
Дата сообщения: 21.09.2008 04:18
Подскажите пожалуйста.
Есть таблица Access под названием Persons с полями(ID,name,surname,lastname). Как занести в нее данные с формы Delphi, если предполагается, что пользователь заполнит поля Edit на форме вручную. По нажатию кнопки данные должны заносится в таблицу.
Как должен выглядеть обработчик кнопки?
Автор: Aquest
Дата сообщения: 24.09.2008 01:25
Как сделать, чтобы в списке компонента Delphi DBComboBox, выпадали значения, содержащиеся в определенном поле таблицы базы данных.

Добавлено:
Как сделать, чтобы в списке компонента Delphi DBComboBox появлялись данные из определенного поля таблицы базы данных?
Автор: ShIvADeSt
Дата сообщения: 24.09.2008 05:36
Aquest

Цитата:
Как сделать, чтобы в списке компонента Delphi DBComboBox появлялись данные из определенного поля таблицы базы данных?

Использовать DBLookupComboBox.
Автор: Aquest
Дата сообщения: 02.10.2008 14:41
Какой переменной можно присвоить результаты запроса, при условии, что в результате запроса отбирается только одно значение поля (имеющего числовой тип)? Как выглядит операция присваивания в данном случае в Delphi?
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select ID_Region From TB_Region');
ADOQuery1.SQL.Add('Where Region='''+DBLookupComboBox1.Text+'''');
ADOQuery1.Open;
В результате отобрано одно значение.
Какой переменной(и как?) его присвоить, чтобы в дальнейшем можно было это значение
вставить в другую таблицу согласно инструкции:
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text:= 'insert into Country (Region) Values (Region)';
ADOQuery1.Parameters.ParamByName('Region').Value :=// Переменная??????????;
ADOQuery1.ExecSQL;
Автор: Coltrain
Дата сообщения: 02.10.2008 15:39
Aquest

var
LID_Region : integer;


Цитата:
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select ID_Region From TB_Region');
ADOQuery1.SQL.Add('Where Region='''+DBLookupComboBox1.Text+'''');
ADOQuery1.Open;

ADOQuery1.First;
LID_Region := ADOQuery1.FieldByName('ID_Region').AsInteger;
.....

Цитата:
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text:= 'insert into Country (Region) Values (Region)';

ADOQuery1.Parameters.ParamByName('Region').Value := LID_Region;

Цитата:
ADOQuery1.ExecSQL;


И еще. Как мне кажется, правильнее запрос на вставку писать как 'insert into Country (Region) Values (?Region)'
Автор: Aquest
Дата сообщения: 02.10.2008 21:55
Coltrain
спасибо, вставка заработала как и предполагалсь!!!!!

Страницы: 1

Предыдущая тема: XML (Packed_XML)


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.