500+ FAQ по Delphi

Перейти на: Главную | Индексную | Предыдущую | Следующую страницу
Курс изучения делового этикета в Москве.

При попытке выполнения такого оператора SQL - "DELETE from T39 T39C0 WHERE T39C0.F1LHT35=253291661" SQL-сервер ругается на недопустимый синтаксис. В чем я неправ?

В данном случае, видимо, T39C0 расценивается как псевдоним. Hо стандартом SQL-92 такое запрещено в DELETE.

Цитата собственно из этого стандарта (сборник из delete и names and identifiers, определение identifier пропущено, просто набор <simple latin letter> | <digit>, начинается с буквы):

Format
<delete statement: positioned>::=
delete from <table name> where current of <cursor name>

<table name> ::= <qualified name> | <qualified local name>
<qualified name> ::= [<shema name><period>] [<qualified identifier>]
<qualified identifier> ::=<identifier>
<shema name>::=[<catalog name><period>]<unqualified shema name>
<unqualified shema name>::=<identifier>
<catalog name>::=<identifier>
<qualified local name>::= MODULE <period><local table name>
<local table name>::=<qualified identifier>
Стандартом запрещено вот такое

select test.a, p_test.a from test p_test;

вот это не по стандарту, хотя Microsoft SQL Server такое ест.

Lilya Kozlenko
li@relex.ru

При разрушении обьектов, порожденных от TDataSet (TTable, TQuery), не отрабатывает событие OnBeforeClose. Что делать?

Недоработка в VCL.

Сейчас вышел из ситуации так: в TForm.OnClose, т.е. пока ещё все компоненты формы живы, делаю CloseDatabases(Self).

В режиме отладки приложения не разрешается доступ (открытие) базы данных. Как лечить?

Необходимо отключить (деинсталлировать через Oracle Installer) Trace Service на клиенте - совет от ORACLE.

Глюк имеет место быть только под Windows NT 4.xx.

Sergey Klochkovski
(2:5080/60.3)

Как заставить Oracle анализировать все таблицы базы данных?

Конечно, можно использовать DBMS_SQL, DBMS_JOB...

А можно и так:

#!/bin/sh
#
# Analyze all tables
#

SQLFILE=/tmp/analyze.sql
LOGFILE=/tmp/analyze.log

echo @connect dbo/passwd@ > $SQLFILE

$ORACLE_HOME/bin/svrmgrl <<EOF | awk \
'/^TABLE/ { print "ANALYZE TABLE DBO." $2 \
" ESTIMATE STATISTICS"; print "/"; }' >> $SQLFILE
connect dbo/passwd
SELECT 'TABLE', TABLE_NAME FROM all_tables WHERE owner = 'DBO';
EOF

echo exit >> $SQLFILE
cat $SQLFILE > $LOGFILE

cat $SQLFILE | $ORACLE_HOME/bin/svrmgrl >> $LOGFILE

cat $LOGFILE | /usr/bin/mailx -s 'Analyze tables' tlk@nbd.kis.ru

rm $SQLFILE
rm $LOGFILE

Anatoly Kuznetsov
tlk@nbd.kis.ru
(2:5015/4.1)

Как программно изменить LangDriver для таблиц dBase и Paradox?

Откpываешь help и смотpишь:

.......
var List:TStrings;
.......
BEGIN
.......
List.Add ( 'LANGDRIVER=db866ru0 ');
.......
Session.ModifyDriver( 'DBASE', List );
.......
END;

Это действие я пpовожy пеpед откpытием таблицы

Ivan Sboev
(2:5049/36.15)

-----------

Это о "русификации" таблицы. В таблицах dBase и Paradox имеется байт, который определяет CodePage содержимого таблицы. Раньше он не использовался и был зарезервирован. Тебе нужно его правильно установить. Это делается через DBD Restructure table. Если хочешь программно, можешь воспользоваться следующей процедурой:

uses DbiTypes, DbiProcs, DbiErrs, DB, WinProcs, SysUtils;

procedure ChangeLangDriver( DatabaseName, TableName, LDName: string );
var
TblExt: string;
Database: TDatabase;
TblDesc: CRTblDesc;
OptDesc: FLDDesc;
OptData: array [0..250] of Char;
Cur: hDBICur;
Rec: CFGDesc;
begin
if ( TableName='' ) or ( LDName='' ) then
raise Exception.Create( 'Unknown TableName or LDName' );
Database:=Session.OpenDatabase( DatabaseName );
try
if Database.IsSQLBased then raise Exception.Create( 'Function ChangeLangDriver working only with dBase or Paradox tables' );
FillChar( OptDesc, SizeOf( OptDesc ), #0 );
FillChar( TblDesc, SizeOf( TblDesc ), #0 );
StrCopy( OptDesc.szName, 'LANGDRIVER' );
OptDesc.iLen := Length( LDName ) + 1;
with TblDesc do
begin
StrPCopy( szTblName, TableName );
TblExt := UpperCase( ExtractFileExt( TableName ) );
if TblExt = 'DBF' then StrCopy( szTblType, szDbase )
else if TblExt = '.DB' then StrCopy( szTblType, szParadox )
else
begin
AnsiToOEM( StrPCopy( OptData, DatabaseName ), OptData );
if DbiOpenCfgInfoList( nil, dbiREADONLY, cfgPersistent,
StrPCopy( OptData, '\DATABASES\' + StrPas( OptData ) + '\DB INFO\' ),
Cur ) <> DBIERR_NONE
then
raise Exception.Create( 'Unknown table type');
try
while DbiGetNextRecord( Cur, dbiNOLOCK, @Rec, nil ) <> DBIERR_EOF do
if StrComp( Rec.szNodeName, 'DEFAULT DRIVER' ) = 0 then
begin
StrCopy( szTblType, Rec.szValue );
Break;
end;
finally
Check( DbiCloseCursor( Cur ) );
end;
end;
iOptParams := 1;
pfldOptParams := @OptDesc;
pOptData := @OptData;
end;
StrPCopy( OptData, LDName );
Check( DbiDoRestructure( Database.Handle, 1, @TblDesc, nil,
nil, nil, False ) );
finally
Session.CloseDatabase( Database );
end;
end;

Примеры использования:

ChangeLangDriver( 'DBDEMOS', 'EMPLOYEE', 'ancyrr' );
ChangeLangDriver( 'DBDEMOS', 'EMPLOYEE.DB', 'ancyrr' );
ChangeLangDriver( 'C:\DELPHI\DEMOS\DATA', 'CLIENTS.DBF', 'db866ru0' );

LDName:
для D1 - имя .LD файла в каталоге IDAPI\LANGDRV;
для D2 и CB - из BDECFG32.HLP поле Short name в табличке по указателю language drivers, dBASE или поле Internal в табличке по указателю language drivers, Paradox;
для D3 и выше - не знаю так как у меня её нет, но думаю, что также, как и в D2.

Farid Zaripov
farid@aduis.kiev.ua
(2:463/201.101)

У меня есть текстовые файлы, которые я хочу использовать в запросах к DB2, но не хочу создавать из них постоянные таблицы в базе. Что делать?

Можно воспользоваться табличными функциями (Table Functions). Они позволяют использовать файлы как таблицы. Примеры приведены в руководстве "Embedded SQL Programming Guide".

Существует ли средство для вывода определения структуры таблицы?

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

Для этого существует утилита DB2LOOK. Она находится в SQLLIB\MISC.

Пример использования:

CONNECT TO SAMPLE USER xxx USING yyy
DB2LOOK -d SAMPLE -u xxx -e -t employee

Вывод может быть перенаправлен в файл.

Полный синтаксис выдаётся по команде:

DB2LOOK ?

Vadim Rumyantsev
(2:5030/48.400)

Поясните, чем в Oracle являются понятия Instance, Database etc.?

Перевод документации:

Что такое ORACLE Database?
Это данные которые будут обрабатываться как единое целое. Database состоит из файлов операционной системы. Физически существуют database files и redo log files. Логически database files содержат словари, таблицы пользователей и redo log файлы. Дополнительно database требует одну или более копий control file.
Что такое ORACLE Instance?
ORACLE Instance обеспечивает программные механизмы доступа и управления database. Instance может быть запущен независимо от любой database (без монтирования или открытия любой database). Один instance может открыть только одну database. В то время как одна database может быть открыта несколькими Instance.

Instance состоит из:
SGA (System Global Area), которая обеспечивает коммуникацию между процессами;
до пяти (в последних версиях больше) бэкграундовых процессов.
От себя добавлю - database включает в себя tablespace, tablespace включает в себя segments (в одном файле данных может быть один или несколько сегментов, сегменты не могут быть разделены на несколько файлов). segments включают в себя extents.

Alex Kravets
(2:5020/904.12)

Почему при создании таблицы Paradox с первичным нечувствительным к регистру индексом вываливается ошибка?

В Парадоксе первичный индекс всегда CaseSensitive.

Как засунуть в качестве паpаметpа хpанимой пpоцедуpы стpоку длиной более 255 символов? И вообще, как использовать паpаметpы SP, если они BLOB?

"Засунуть" длинную строку можно было и раньше, если написать редактируемый запрос, и воспользоваться операциями Insert/Edit.

Однако это не относится к хранимым процедурам.

В Delphi 3.0 появился новый тип параметра (TBlobField вроде) и соответственно его поддержка в BDE.

Если просто взять BDE 4.01 и выше, то работать все-равно не будет - нужна соотв. версия VCL (из Delphi 3.0 или выше).

Dmitry Kuzmenko

-------------

Т.е. - переходите на Delphi 3.02 или выше, или используйте альтернативные способы - типа представлений, обновляемых с помощью триггеров.

Как работать из Delphi напрямую с MS ADO (Microsoft Active Data Objects)?

Итак, хочу поделиться некоторыми достижениями... так на всякий случай. Если у вас вдруг потребуется сделать в своей программке доступ к базе данных, а BDE использовать будет неохота (или невозможно) - то есть довольно приятный вариант: использовать ActiveX Data Objects. Однако с их использованием есть некоторые проблемы, и одна из них это как передавать Optional параметры, которые вроде как можно не указывать. Однако, если вы работаете с ADO по-человечески, а не через тормозной IDispatch.Invoke то это превращается в головную боль. Вот как от нее избавляться:

var
OptionalParam: OleVariant;
VarData: PVarData;
begin
OptionalParam := DISP_E_PARAMNOTFOUND;
VarData := @OptionalParam;
VarData^.VType := varError;

после этого переменную OptionalParam можно передавать вместо неиспользуемого аргумента.

Далее, самый приятный способ получения Result sets:

Там есть масса вариантов, но как выяснилось оптимальным является следующий вариант, который позволяет получить любой желаемый вид курсора (как клиентский, так и серверный)

var
MyConn: _Connection;
MyComm: _Command;
MyRecSet: _Recordset;
prm1: _Parameter;
begin
MyConn := CoConnection.Create;
MyConn.ConnectionString := 'DSN=pubs;uid=sa;pwd=;';
MyConn.Open( '', '', '', -1 );
MyCommand := CoCommand.Create;
MyCommand.ActiveConnection := MyConn;
MyCommand.CommandText := 'SELECT * FROM blahblah WHERE BlahID=?'
Prm1 := MyCommand.CreateParameter( 'Id', adInteger.adParamInput, -1, <value> );
MyCommand.AppendParameter( Prm1 );
MyRecSet := CoRecordSet.Create;
MyRecSet.Open( MyCommand, OptionalParam, adOpenDynamic, adLockReadOnly, adCmdText );

... теперь можно фетчить записи. Работает шустро и классно. Меня радует. Особенно радуют серверные курсоры.

Проверялось на Delphi 3.02 + ADO 1.5 + MS SQL 6.5 sp4. Пашет как зверь.

Из вкусностей ADO - их легко можно использовать во всяких многопоточных приложениях, где BDE порой сбоит, если, конечно, ODBC драйвер грамотно сделан...

Ну и еще можно использовать для доступа к данным всяких там "нестандартных" баз типа MS Index Server или MS Active Directory Services.

Alexey Kopernick
(2:5020/221)

-------------

В Delphi (как минимум в 4 версии) существует "константа" EmptyParam, которую можно подставлять в качестве пустого параметра.

После снесения через родной uninstall Interbase Server 5.0 для Windows и желания поставить 5.1.1 вылетает ошибка: IBCheck. Что делать?

Решение найдено. Прочитай сам и передай товарищу:

Надо запустить regedit, и открыть ключ

HKEY_LOCAL_MACHINE\Environment

Там есть строка PATH. Так вот иногда она почему-то становится не строкой, а еще чем-то. Ее надо убить, и пересоздать как строку, прописав туда прежнее содержимое (в виде строки).

Dmitry Kuzmenko

Как узнать текущие дату и время в Interbase?

Дата + время - DATE.

Только дата - TODAY.

Только время - DATE-TODAY.

Сяржук Казачэнка

Делаем ApplyUpdates. Если пpи insert(update) пpоизошла ошибка (поле null, сpаботал check, etc.), то BDE всегда говоpит "General SQL Error" вместо ноpмального сообщения об ошибке :-( Без CU все ноpмально, pазумеется. Как боpоть этот баг?

Использyй ноpмальнyю тpансляцию ошибок в Application.OnException.

Вpоде это.

procedure DBExceptionTranslate(E: EDBEngineError);

function OriginalMessage: String;
var
I: Integer;
DBErr: TDBError;
S: String;
begin
Result := '';
for I := 0 to E.ErrorCount - 1 do
begin
DBErr := E.Errors[I];
case DBErr.NativeError of
-836: { Intebase exception }
begin
S := DBErr.Message;
Result := #13#10 + Copy(S, Pos(#10, S) + 1, Length(S));
Exit;
end;
end;
S := Trim(DBErr.Message);
if S <> '' then Result := Result + #13#10 + S;
end;
end;

begin
case E.Errors[0].ErrorCode of
$2204:
E.Message := LoadStr(SKeyDeleted);
$271E,$2734:
E.Message := LoadStr(SInvalidUserName);
$2815:
E.Message := LoadStr(SDeadlock);
$2601:
E.Message := LoadStr(SKeyViol);
$2604:
E.Message := LoadStr(SFKViolation) + OriginalMessage;
else
begin
E.Message := Format(LoadStr(SErrorCodeFmt), [E.Errors[0].ErrorCode]) +
OriginalMessage;
end;
end;
end;

Vladimir Gaitanoff
(2:5017/5.69)

Как открыть индексированную таблицу dBase, если отсутствует файл индекса?

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

Для этого в заголовок файла dbf по смещению 28(dec) записываешь 0.

По другому никак не выходит(я долго бился)- вот для Paradox таблиц все Ok.

Олег
oleg@avia.cmw.ru

-----------

С помощью BDE Callbacks. Пpимеp для Delphi 2.0, на пеpвом не пpовеpял:

=== Callback.pas ===
unit Callback;

interface

uses BDE, Classes, Forms, DB, DBTables;

type
TForm1 = class(TForm)
Table1: TTable;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
CBack: TBDECallback; // опpеделение BDE CallBack
CBBuf: CBInputDesc; // пpосто буфеp
function CBFunc(CBInfo: Pointer): CBRType; // Callback-функция
public
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
Session.Open; // В это вpемя сессия ещё не откpыта
CBack := TBDECallback.Create( Session {Hапpимеp}, nil, cbINPUTREQ, @CBRegBuf,
SizeOf(CBBuf), CBFunc, False); // Опpеделили Callback
Table1.Open;
//^^^^^^^^^^^ - здесь возможна ошибка с индексом, etc.
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
CBack.Free; // Освобождаем CallBack
end;

function TForm1.CBFunc(CBInfo: Pointer): CBRType;
begin
with PCBInputDesc(CBInfo)^ do
case eCbInputId of
cbiMDXMissing {, cbiDBTMissing - можно ещё и очищать BLOB-поля}:
begin
iSelection := 3; // Hомеp ваpианта ответа (1-й - откpыть только
// для чтения, 2-й - не откpывать, 3-й - отсоединить индекс).
// Возможный источник непpиятностей: а вдpуг в последующих веpсиях
// BDE номеpа будут дpугими?
Result := cbrCHKINPUT; // Обpабатывать введённый ответ
end;
end;
end;

end.
=== Callback.pas ===

PS: конечно, это лишь пpимеp, делающий минимум необходимого. В pамках данного письма невозможно дать какое-то описание BDE Callbacks. Инфоpмацию я взял из BDE32.HLP, BDE.INT и DB.PAS. В VCL.HLP совсем ничего нет по этому поводу.

Вообще, pуки бы отоpвал тем, кто писал спpавку по Дельфям: я неделю мучался с сабжем, пока случайно не набpёл на Callbacks.

Denis Zaytsev
(2:5011/49.6)

Всегда рады ответить на Ваш вопрос, нужен юрист.

Материалы находятся на сайте http://cracklab.narod.ru/faq/


Создатель этого HTML файла не претендует на авторство вопросов/ответов представленных в нём, не отвечает за их содержание и достоверность, а также за последствия использования программных кодов , полученных из этого HTML файла. Также не принимаются претензии относительно не размещённой информации об авторе каждого конкретного FAQ'а. Любые другие вопросы присылайте на bad_guy@cracklab.ru (обращаться к Bad_guy'ю).
Hosted by uCoz