Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Универсальная обработка DELPHI+FireBird+ibtable есть вопрос помогите!  (Прочитано 17731 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Fatal_Error
Участник

ru
Offline Offline
Пол: Мужской

« : 18-08-2009 08:14 » 

Здравствуйте!
захотелось зделать универсальную обработку для пользователей, смысл обработки такой что пользователь выбирает базу данных *.fdb и други не принципиально. выбирает нужную ему таблицу в базу а потом выбирает нужное ему поле. к примеру "ID". так вот значения всех записей этого поля равно "1" а нужно их поменять к примеру на "0". он вводит edit новое значение выбирает поле в котором нужно опменять жмёт одну кнопку и все значение всех записей меняется.=) (не спрашивайте для чего мне это, на само деле тут очень глубокий смысл.) сам коркас программы я написал но вот к "универсальности у меня дело не подходит"

ну выбор базы и прочее я решил просто:

открываю нужную базу
Код:
form1.OpenDialog1.Execute;
form1.IBDatabase1.DatabaseName:=form1.OpenDialog1.FileName;
form1.IBDatabase1.Connected:=true;
form1.IBTransaction1.Active:=true;

выбираю нужную таблицу в базе (правдо вводить нужно вручную. не суть)
Код:
form1.IBTable1.TableName:=form1.Edit1.Text;
form1.IBTable1.Active:=true;

что бы юзер мог тупо выбрать из списка нужное ему поле , делаю это

Код:
form1.ComboBox1.Items:=form1.IBTable1.FieldList;

тип данных выбирается тем же макаром что и поля.


теперь самое интерестно..первоначально мою голову поситила идею написать следующее для обработки



Код:
var i:integer;

begin


i:=0;
form1.IBTable1.First;
for i:=0 to form1.IBTable1.RecordCount do
begin

form1.IBTable1.Edit;

//form1.IBTable1.FieldByName({тут хотел вписывать значение поля}form1.ComboBox1.Items.text).{тут тип данных, выбирается по такомуже принципу что и поле из раскрывающегося списка}:={новое значение которое вобъёт узер};

{короче в итоге эта строчка выгледила бы так}
 form1.IBTable1.FieldByName(form1.ComboBox1.Items.text).edit6.text:={новое значение которое вобъёт узер};
form1.IBTable1.Post;


form1.IBTable1.Next;
end;
{}
end;

конечно же это не работало Быть такого не может. как можно это решить по другому. может както можно другим способом сформировать команду или что то ещё???
 Здесь была моя ладья... Не понял
тоесть так что бы пользователь такая мышка и выбирая из списков значения набирал своего рода код будущей процедуры котора я в последующем выполнялась. если так будет более понятно что я хочу зделать=)) спасибо !!!
« Последнее редактирование: 18-08-2009 08:16 от Fatal_Error » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #1 : 18-08-2009 08:27 » 

наверное, поможет ... IBExpert Улыбаюсь

или SQL-запрос
update TABLE set FIELD=VALUE
Записан

Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 18-08-2009 08:31 » 

update на всю таблицу
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Fatal_Error
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 18-08-2009 10:24 » 

скрипт это понятно. а если чувак полный даун. как здалеть так что бы нажимая определённые кнопки он формировал код программы(грубо говоря какуюто процедуру) а потом этот код выполнялся. вот что я хочу. а кнопки просто ....типо
1) жми сюда
2) потом жми сюда
3) и в конце жми сюда
что бы он каким то образом формировал код. или строку в коде ти вот этой
Код:
form1.IBTable1.FieldByName({тут хотел вписывать значение поля}form1.ComboBox1.Items.text).{тут тип данных, выбирается по такомуже принципу что и поле из раскрывающегося списка}:={новое значение которое вобъёт узер};
Здесь была моя ладья... Не понял
и что бы его руки шаловливые некуда больше ни лезли. тоесть что бы дальеш моей прогрммки он ринутся не смог
« Последнее редактирование: 18-08-2009 10:26 от Fatal_Error » Записан
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #4 : 18-08-2009 12:02 » 

Fatal_Error, причем здесь даун? Твоя программа должна собрать SQL-запрос, подставив в него данные, что введет пользователь и запустить полученный SQL-запрос.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #5 : 18-08-2009 16:04 » 

Цитата
Код:
form1.IBTable1.FieldByName({тут хотел вписывать значение поля}form1.ComboBox1.Items.text).{тут тип данных, выбирается по такомуже принципу что и поле из раскрывающегося списка}:={новое значение которое вобъёт узер};

любое поле имеет свойство AsString, соответственно, можно проще:

Код:
  IBTable1.Edit;
  IBTable1.FieldByName(ComboBox1.Items.text).AsString := Edit1.Text;
  IbTable1.Post;

обрати внимание, что работая в методах формы тебе не надо указывать имя формы при обращении к её же компонентам.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #6 : 18-08-2009 16:08 » 

т.е. для начала можно не выбирать тип обновляемого поля, а принудительно приводить всё к нужному тебе типу. если юзер пишет новое значение в TEdit - оно будет строковым. вот и пиши его как строку, - через AsString.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #7 : 18-08-2009 16:13 » 

Цитата
выбираю нужную таблицу в базе (правдо вводить нужно вручную. не суть)

посмотри на две процедуры у TIbDatabase:

Код:
    procedure GetTableNames(List: TStrings; SystemTables: Boolean = False);
    procedure GetFieldNames(const TableName: string; List: TStrings);

первая получает список всех таблиц (при желании - и системных тоже)
вторая - для выбранной таблицы получает список всех полей.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #8 : 18-08-2009 16:31 » 

наверное, поможет ... IBExpert Улыбаюсь

или SQL-запрос
update TABLE set FIELD=VALUE

update на всю таблицу
Fatal_Error, причем здесь даун? Твоя программа должна собрать SQL-запрос, подставив в него данные, что введет пользователь и запустить полученный SQL-запрос.

давать возможность юзеру выполнять компонуемые запросы над базой - более чем нетривиальна. потому что она сводится к написанию собственного парсера запроса либо танцами с бубном при настройке прав.

в то же время во многих АИСах встаёт задача bulk-апдейтов. есть у нас список неких заданий (заказов, имён файлов - не суть), и надо поменять в одной таблице значение одного поля. если в конторе есть админ - то он сам и поменяет. а когда прога работает в другом городе, да ещё на каком-нибудь секурном предприятии - начинается геморрой.

поэтому для любой нормальной АИС делается возможность настраиваемых обновлений (равно как и возможность настраиваемых дампов данных из любой таблицы, и многое другое).

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

что на самом деле пишет автор и на самом ли деле ему это надо - вопрос отдельный.
Записан

zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #9 : 18-08-2009 17:17 » 

x77, вариант, который предлагает автор темы, а именно тупой перебор таблицы, в любом случае предполагает возможный сценарий действий пользователя. Собственно данный вариант легко описывается SQL-строкой:
IBQuery1.SQL.Text := 'UPDATE MyTable SET ' + ComboBox1.Items.text + '=' + '''' + edit6.text + '''';
Так неужели лучше тупо перебирать таблицу (а если там десятки тысяч записей?) или все таки выполнить один SQL-запрос, который легко можно сконструировать из действий пользователя?
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #10 : 19-08-2009 06:23 » new

zubr, тут спорно. есть разница между выполнением запроса на клиенте (тупой перебор) и на сервере (запрос типа update). если ты гарантируешь, что сервак создаёт отдельный процесс на каждое подключение - оптимальнее запрос на сервере. если сервак создаёт отдельную нить на каждое подключение - при выполнении часового апдейта у тебя на час зависнут все соединения.

в общем случае ты не знаешь, какая архитектура FB юзается у клиента. поэтому в общем случае - лучше делать обновления на клиенте.

и потом, я же не говорю, что автор делает оптимально. я говорю, что он "движется в правильном направлении". есстественно, что в реальной жизни для подобных апдейтов юзается не буферизованный IbTable, а однонаправленный IbSql. даже на больших объёмах он может дать вполне приличные скорости.
Записан

Fatal_Error
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 20-08-2009 00:42 » 

 Ага Привет ребят! Вижу тут поднялась дискусия. Попытаюсь рассказать о всём по порядку.
Начну так сказать с главного, для чего мне это нужно и что именно я хочу решить.
1)
Цитата
поэтому для любой нормальной АИС делается возможность настраиваемых обновлений (равно как и возможность настраиваемых дампов данных из любой таблицы, и многое другое).

и вот такие вещи делаются именно так, как пытается сделать автор: выбор из списка допустимых таблиц, выбор из списка допустимых полей, указание диапазона, ввод нового значения. у пользователя ни в коем случае не должно быть возможности выполнить на сервере произвольный запрос.
Именно это я и хочу зделать, тоесть суть проблемы токова, что есть некая база которая крутится на firebird, и софт(клиент) к ней, дело в том что в данной программе не предусмотренны некоторые групповые обработки, тоесть к примеру нельзя выделить все зписи из справочника контрагентов и присвоить груповой операцией им к примеру скидку 15%...приходится выбирать каждого контрагента ставить ему эту скидку и переходить на следующего. Раньше я выполнял подобные действи через IBExpert, но из за увелечения объёмов подобных проблем решил это автоматизировать, так же есть удалённые офиса, и тратить весь день на капризы манагеров(то они хотят к примеру 5% то 10%) мне просто физически не потянуть. А зделав такую программулину я очень грамотно а главное с "контролем"(тоесть узер не натворит ничего лишнего) смогу возлажить это на плечи самих пользователей. Непосредствоенно про действия со скидкой я взял для примера, подобных задач на самом деле придостаточно. Дожидатся решения проблемы самими разработчиками софта я отчаился ждать, уже с каким релизом такие моменты никак не решаются, темболее что софт отечественный что собственно всё усугубляет. Ходить долеко ненадо что софт что автопром=))))))) Быть такого не может
2)различные выводы и предположения:
Цитата
вариант, который предлагает автор темы, а именно тупой перебор таблицы
я ничего не хочу перебирать покачто, хочу понять на примере элементарного действия над базой как мне это лучще реализовать и с какой стороны подойти к этой проблеме, поэтому и прошу совета у вас уважаемые форумчани Да-да я знаю что этот форум очень хороший, пишу я сдесь редко, восновном использую решения для уже возникавших проблем(просматривая посты).

Из сказанного вами(за что спасибо) я понял следующее:
а)На IBTable зделать можно, как предложил x77, не годится для этих целей, софт будит сильно нагружать базу
б) Лучще использовать IbSql. Тоесть тоесть пользователь нажимаю кнопки будит формировать SQL запрос, соответсвенно для вопсриятия пользователем информации в списке "команды" sql будут называтся подругому. теперь только остаётся продумать нужные мне запросы и дать пользователю их конструировать(в удобном и понятном простому обывателю интерфейсе)


Ребят то что вы мне посоветовали я если честно ещё даже не попробывал по этому по техническим моментам и результатам ничего сказать немогу, приму ваши советы вовнимание Скромно так... Ага
Эту тему оставляю открытой потомучто уверен что у меня возникнут ещё вопросы, да и могут возникнуть у тех кто решил зделать подобное=).
спасибо. не забывайте про мою тему. сегодня постараюсь прогнать новые идеи. если что отпишу Что, съел?







« Последнее редактирование: 20-08-2009 00:53 от Fatal_Error » Записан
Fatal_Error
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 20-08-2009 00:59 » 

 :-/Начал перечитывать ещё внимательней возник вопрос по поводу вот этого:
Цитата
zubr, тут спорно. есть разница между выполнением запроса на клиенте (тупой перебор) и на сервере (запрос типа update). если ты гарантируешь, что сервак создаёт отдельный процесс на каждое подключение - оптимальнее запрос на сервере. если сервак создаёт отдельную нить на каждое подключение - при выполнении часового апдейта у тебя на час зависнут все соединения.

Если я правильно вас понял то данный софт, работает не по приницпу хранимых процедур которые создны в базе и клиент посылает команды на их выполнение, а всё вшито в сам клиент.

Цитата
в общем случае ты не знаешь, какая архитектура FB юзается у клиента. поэтому в общем случае - лучше делать обновления на клиенте.
подскажите как мне определится с этим моментом и в каком направлении мне дельше плыт=) ещё раз спасибо!!!
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #13 : 20-08-2009 10:30 » 

:-/Начал перечитывать ещё внимательней возник вопрос по поводу вот этого:
Цитата
zubr, тут спорно. есть разница между выполнением запроса на клиенте (тупой перебор) и на сервере (запрос типа update). если ты гарантируешь, что сервак создаёт отдельный процесс на каждое подключение - оптимальнее запрос на сервере. если сервак создаёт отдельную нить на каждое подключение - при выполнении часового апдейта у тебя на час зависнут все соединения.

это нюансы, честно говоря. пока можно не заморачиваться.

Цитата
Если я правильно вас понял то данный софт, работает не по приницпу хранимых процедур которые создны в базе и клиент посылает команды на их выполнение, а всё вшито в сам клиент.

если вы выполняете запрос update table1 set field1='A' - он будет выполняться полностью на стороне сервера. то же самое, если вы пишете хранимую процедуру, которая выполняет этот запрос. а вот при таком коде:
Код:
form1.IBTable1.First;
for i:=0 to form1.IBTable1.RecordCount do
вся работа происходит на стороне клиента. и это заведомо медленне, о чём и писал zubr.

Цитата
Цитата
в общем случае ты не знаешь, какая архитектура FB юзается у клиента. поэтому в общем случае - лучше делать обновления на клиенте.
подскажите как мне определится с этим моментом и в каком направлении мне дельше плыт=) ещё раз спасибо!!!

есть две архитектуры FB: суперсервер (один процесс, на каждое подключение - создаётся отдельный поток) и классик (на каждые подключение создаётся отдельный процесс). я предпочитаю классик, он стабильнее, и при зависании одного подключения это гарантировано не затрагивает остальные. архитектура выбирается в момент инсталляции СУБД. и позже может быть изменена на нужную вам. определить, какая используется у вас можно по кол-ву процессов FB. при десятке подключении у классика на сервере в диспетчере задач будет 10 процессов, а у суперсервера - одно.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #14 : 20-08-2009 10:57 » 

Цитата
я ничего не хочу перебирать покачто, хочу понять на примере элементарного действия над базой как мне это лучще реализовать

сначала надо сформулировать задачу Улыбаюсь

1. требуется предоставить возможность пользователю выполнять пакетные обновления записей.
вопросы:
  1.1. над всеми таблицами?
  1.2. только над определёнными таблицами?
  1.3. по любому полю таблицы?
  1.4. по заданному списку полей таблицы?
  1.5. над всеми записями?
  1.6. только над записями определённого диапазона?

очевидно, что есть таблицы и поля, куда пользователя пускать нельзя. более того, будут и записи, куда его пускать нельзя. к примеру пользователь хочет сделать скидку по всем заказам, очевидно, что эта операция не должна затрагивать уже закрытые или проплаченные заказы.

все эти ограничения условно можно разбить на две группы: статические и динамические. список доступных для изменения таблиц, и список полей по каждой таблице тебе известен заранее - его можно хранить в БД или прошить в программу. но могут быть и динамически ограничения, например, какие-то поля можно менять только при определённых значениях совсем других полей в других таблицах. я бы пока не трогал эти варианты. допустимые диапазоны выборок - тоже весёлая и интересная песня, но о ней чуть позже.

словом, задача этапа 1 - это определиться, "что может менять пользователь".
 
2. надо решить, как пользователь будет менять записи. очевидно, что нельзя давать возможность манагеру делать скидку 100%. из всех таблиц и полей, которые мы разрешили ему менять в п.1. надо выделить те таблицы и поля, на значения которых должны налагаться ограничения, и для каждого случая эти ограничения надо внятно сформулировать.

вот это - основное, с чего надо начинать. дальше можно будет поговорить о логировании действий, откате действий, и многом другом.


Записан

Fatal_Error
Участник

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 21-08-2009 09:21 » 

 Внимание! Говорит и показывает... x77 Спасибо! за выходные я всё обдумаю и переварю и попробую.
Цитата
1. требуется предоставить возможность пользователю выполнять пакетные обновления записей.
вопросы:

Цитата
словом, задача этапа 1 - это определиться, "что может менять пользователь".
 
2. надо решить, как пользователь будет менять записи.

поэтому плану я накидаю свои мысли, как  я вижу эти моменты относительно нашей С ума сойти... базы данных=)
посоветуюсь с пользователями что конкретно они хотели бы изменять.

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

Захожу немного вперёд, вообще я хочу зделать следующее что бы к программе щёл так называемый конфигурационный файл, в котором кокраз бы и прописывалось к каким базам, таблицам, полям, какие поля можно менять и на сколько  и т.п имеет доступ пользователь, какие операции он может выполнять(отграничение на уровне клиента а не на уровне сервера). Исходя из этих настроек можно было бы получить и так называемую "админку" и рабочее место пользователя.
Конечно любой опытный пользователь может поправить файл конфигурации, так вот здесь я ещё покачто не сообразил. На данный моменте есть два моих варианта, либо каким то образом запрещать его редактирование и изменение или зделать так что бы он был обычным *.INI но параметры использующиеся там были бы так сказать "защифрованы", тоесть написанны не четабельным и невопсринимающимся на первый взгляд сокрашениями. Тоесть к примеру параметр "default" (английский мало мальски знает каждый), пусть в программу на финише он будит поступать как default, но в *.ini будит писаться к примеру как "id=1", никто же из пользователей не разберёт что будит значить "id=2", "id=3" И Т.П и есть ли они вообще. Описание таких параметров будит доступно только системному администратору. Можно пойти ещё дальще и зделать небольшой модуль для изменения файла конфигурации в удобном интерфейсе к примеру для топ менеджера который имеет на это право.
Ну это я так планы на будущее. Быть такого не может.

Покачто задача набар уан, попробывать то что посоветовали Вы, и собрать мысли в кучу по плану x77

Интерфейс будущей программки я уже маленько накидал, небольшой функциональ тоже. Ниже скрин. не судите строго, по поводу красоты покачто не заморачивался.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #16 : 26-08-2009 13:53 » 

к программе щёл так называемый конфигурационный файл, в котором кокраз бы и прописывалось к каким базам, таблицам, полям, какие поля можно менять и на сколько  и т.п имеет доступ пользователь, какие операции он может выполнять(отграничение на уровне клиента а не на уровне сервера). Исходя из этих настроек можно было бы получить и так называемую "админку" и рабочее место пользователя.
<..>
либо каким то образом запрещать его редактирование и изменение или зделать так что бы он был обычным *.INI но параметры использующиеся там были бы так сказать "защифрованы", тоесть написанны не четабельным и невопсринимающимся на первый взгляд сокрашениями

любая эффективная защита может быть построена только на отторжении ключа. всё остальное - это ерунда, и при желании всё это раскопают.

защиту "от дурака" можно было бы сделать так: конфиги хранить в ini-файле, зазипованном по паролю. паролем является, например, <"Fatal_Error"DDMMYY>, где DDMMYY - дата создания конфигурационного файла. при запуске программа вычитывает конфиг, а при выходе удаляет старй конфиг, перезиповывает и записывает новый с паролем по текущей дате.

но самое простое и самое грамотное решение - это хранить права в самой БД.
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines