Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров
Шрифт:
Интервал:
Закладка:
begin
aBlobStream := TBlobStream.Create(TMemoField, bmRead);
TMemo.Lines.LoadFromStream(aBlobStream);
aBlobStream.Free;
end;
Если в транзакции изменена какая-то таблица, то для другого пользователя блокируется вся таблица, до окончания транзакции. Как лечить?
Nomadic отвечает:
По умолчанию, оператор UPDATE в MS SQL Server пытается поставить эксклюзивную табличную блокировку. Вы можете обойти это, используя ключевое слово FROM в сочетании с опцией PAGLOCK для использования MS SQL Server страничных блокировок вместо эксклюзивной табличной блокировки:
UPDATE orders SET customer_id=NULL FROM orders(PAGLOCK) WHERE customer_id=32;
Блокиpовка на всю таблицу пpи UPDATE ставится только в том случае, если по предикату нет индекса. Так, можно просто проиндексировать таблицу orders по полю customer_id, и не забывать делать UPDATE STATISTIC, хотя будет работать и с PAGLOCK. Просто не факт, что UPDATE всегда делает табличную блокировку.
Форма Мастер-Деталь
Delphi 1
…это нормально в двух случаях:
1. Эксперт баз данных по умолчанию создает запрос, где RequestLive установлен в False; если вы хотите что-либо изменить, установите RequestLive в True.
2. При отношениях «один к многим», из-за правил сохранения целостности, вам дозволяется делать изменения только на форме «многих», а не на форме «один».
BTW: правильно, что вы об этом задумались. Предположим, что вы имеете отношение «один к многим», где «один» — ваши клиенты, а «многие» — их счета-фактуры: естественно, счетов, относящихся к клиенту, может быть больше, чем один. Если ваша система позволяет редактировать информацию о клиентах, например, удалять записи, то вскоре вы можете обнаружить, что некоторые счета не будут иметь отношения к кому бы то ни было.
Подскажите как правильно показать на экpане и сохранить в базе картинку формата JPEG?
Nomadic отвечает:
Я делал так (это кусок компонента):
if Picture.Graphic is TJPegImage then
begin
bs:=TBlobStream.Create(TBlobField(Field),bmWrite);
Picture.Graphic.SaveToStream(bs);
bs.Free;
end
else if Picture.Graphic is TBitmap then
begin
Jpg:=TJPegImage.Create;
Jpg.CompressionQuality:=…;
Jpg.PixelFormat:=…;
Jpg.Assign(Picture.Graphic);
Jpg.JPEGNeeded;
bs:=TBlobStream.Create(TBlobField(Field),bmWrite);
Jpg.SaveToStream(bs);
bs.Free;
Jpg.Free;
end else Field.Clear;
Как исключить показ поля P_RECNO?
Delphi 1
Вы можете сделать:
1. отредактируйте TTable для исключения P_RECNO
или
2. установите
TableX.FieldbyName('P_RECNO').Visible := False;
Это можно сделать также и с помощью редактора полей (Fields Editor), который связан не с DBGrid, а напрямую с компонентом Table. Для вызова редактора щелкните правой кнопкой мыши на компоненте Table и выберите самый верхний пункт контекстного меню. Добавьте все поля в список полей и выделите то поле, которое вы не хотите показывать в DBgrid. Найдите в Инспекторе Объектов свойство Visible, и установите его в False.
//
Если у вас имеется компонент TTable, дважды щелкните на иконке компонента (расположенной на форме), и вы получите в диалоге список полей, имеющих отношение к соответствующей таблице щелкните на одном из полей и проверьте в Инспекторе Объектов свойство Visible, оно должно быть установлено в False.
//
Информация из одной таблицы и набора данных на двух формах
1. Добавьте на вторую форму (form2) компонент TTable
2. В режиме разработки присвойте этой таблице такие же значения, как и у таблицы, расположенной на form1
3. В секции IMPLEMENTATION у form2 создайте следующий фрагмент кода:
unit form2;
interface
{…}
implementation
uses form1;
{…}
4. Подключите процедуру к OnCreate-событию в form2 (через Инспектор Объектов)
5. Добавьте к этой процедуре следующую строку:
table1 := form1.table1;
В режиме разработки свяжите все компоненты с table1, расположенным на form1.
Остается только решить проблему синхронизации. Попробуйте следующее:
- На Form1
разместите Table1
разместите DataSource1
установите DataSource1.DataSet := Table1
разместите DataGrid
установите DataSource := DataSource1
Ну это все просто и стандартно. Поехали дальше:
- На Form2
разместите DataSource1 (#1 для этой формы)
разместите любые другие необходимые вам БД-компоненты;
укажите у них в качестве источника данных DataSource1
В обработчике события OnCreate для этой формы (например, FormCreate), поместите следующий код:
With Form1 do
begin
Form2.DataSource1.DataSet := Table1;
end;
Данный код подключает Table1 на Form1 к DataSource от Form2.
После таких действий данные будут отображены на Form2 и будут «синхронизированы» с данными, отображаемыми на Form1 (поскольку в действительности используется одна таблица).
Единственное здесь предостережение – если вы используете TDatabase, так как это может быть не то, что вы хотите. Компонент TDatabase не обязателен для получения доступа к базам данных, но, тем не менее, он обеспечивает вас дополнительным контролем в приложениях класса клиент/сервер.
Таким образом, если приложение не работает в среде клиент/сервер, нет необходимости использовать TDatabase. Все, что вам нужно – TDataSource, TTable и компоненты для работы с базами данных.
Как при вводе информации в БД автоматически вставлять SEQUENCE?
Nomadic отвечает:
Если добавление через оператор INSERT ( в TQuery), то прямо там пишешь, как в плюсе («… Values (My_seq.nextval, …»).
Если добавление идет через TQuery c RequestLive=true, то в BeforeInsert сделай запрос через TQuery (select myseq.nextval from dual) и заноси значение в свое поле.
Помещение переменной в Memo-поле
Delphi 1
Если я правильно понял ваш вопрос, вам нужно сделать приблизительно так (для ПОЛУЧЕНИЯ данных):
Memos := TStringList.Create;
Memos.Assign(Table1Memo);
yourvariable_0 := Memos[0];
yourvariable_1 := Memos[1];
……………………
yourvariable_n := Memos[n];
Memos.Free;
или так (для УСТАНОВКИ данных):
Memos := TStringList.Create;
Memos.Add(yourvariable_0);
Memos.Add(yourvariable_1);
……………………
Memos.Add(yourvariable_n);
Table1Memo.Assign(Memos);
Memos.Free;
Индикатор прогресса выполнения запроса
Delphi 1
Невозможно.
Идея заключалась в том, чтобы с помощью объекта TQuery выполнять запросы, SQL сервер их в фоне обрабатывал бы, а мы смотрели бы на это дело на локальной машине с помощью линейки прогресса. Но из приложения никоим образом нельзя узнать, что делает TQuery, так что линейка прогресса, по идее, должна была бы получать текущую позицию непосредственно с SQL сервера. Но, поскольку большинство SQL серверов не публикуют такой информации, эту идею можно торжественно схоронить…
Если вы используете Paradox или DBase, то, я думаю, для этой цели вы можете воспользоваться функцией DBIRegisterCallback:
Использование:
Обратные вызовы (Callbacks) используются в случае, когда клиентскому приложению необходимо получить (возвратить) информацию о ходе выполнения операции. Функция DBIRegisterCallback позволяет клиенту зарегистрировать обратную связь с BDE, после чего BDE может извещать клиента о наступлении событий.
Из руководства пользователя DBEЛично я никогда этим не пользовался, поэтому на смогу поделиться деталями.
Обновление данных БД из модальной формы
Delphi 1
Возможно следующий код позволит вам использовать ту же самую таблицу и источник данных в модальной форме, что и в вашей главной форме. Попробуйте изменить код модальной формы следующим образом:
unit myModalF;
interface
{…}
implementation
{…}
uses
MainForm; {Имя файла родительской формы для вашей модальной формы}
MyModalForm.OnCreate(Sender: TObject);
begin
DBGrid1.DataSource := MyMainForm.DataSource1;
end;
Как записать в BLOB-поле большой текст (>255 байт) из Delphi?
Nomadic отвечает:
Можно так –
var
S: TBlobStream;
B: pointer;
c: integer;
…
Table1.Edit;
S := TBlobStream.Create(Table1BlobField as TBlobField, bmWrite); {кажется, так}