Sources
Delphi Russian Knowledge Base
DRKB - база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как удалить таблицу?

01.01.2007

Я много работал с клиент-серверным Delphi и MS SQL Server в качестве внутренней базы данных. Операционная модель, которую я использую для своего клиента/сервера, заключается в том, что клиентское приложение действует только как локальный интерфейс, и что все запросы и вычисления - даже временные файлы - выполняются или создаются на сервере. Это создает пару проблем, поскольку очистка мусора не так проста, как при использовании локальных таблиц в качестве временных файлов.

Например, многие из моих программ создают временные файлы, на которые я либо ссылаюсь позже в программе, либо использую в качестве временного хранилища для внешних объединений. Как только я закончу работу с ними, мне нужно будет их удалить. С локальными таблицами это проще простого. Просто получите список таблиц и удалите их с помощью небольшого количества кода, использующего некоторые вызовы Windows API.

Но с таблицами SQL Server не все так просто. Причина в том, что для выполнения задачи вам придется пройти через BDE, а это не обязательно очень интуитивно понятно. К счастью, однако, это не требует низкоуровневых вызовов API BDE.

Ниже приведен список процедур, которые удаляют таблицы из любой базы данных SQL Server. После листинга обсудим детали...

Описание параметров:

//var Ses : TSession;         //A valid, open session
//DBName : String;            //Name of the SQL Server DB
//ArTables : array of String; //An array of table names
//StatMsg : TStatusMsg);      //A status message callback
                              //procedure

TStatusMsg — процедурный тип, используемый в качестве процедуры обратного вызова.

type
  TStatusMsg = procedure(Msg: string);

procedure DropMSSQLTempTables(var Ses: TSession;
  DBName: string;
  ArTables: array of string;
  StatMsg: TStatusMsg);
var
  N: Integer;
  qry: TQuery;
  lst: TStringList;
begin
  lst := TStringList.Create;

  Ses.GetTableNames(DBName, '', False, False, lst);

  try
    for N := Low(arTables) to High(arTables) do
      if (lst.IndexOf(ArTables[N]) > 0) then
      begin
        StatMsg('Removing ' + arTables[N] +
          ' from client database');
        qry := TQuery.Create(nil);
        with qry do
        begin
          Active := False;
          SessionName := Ses.SessionName;
          DatabaseName := DBName;
          SQL.Add('DROP TABLE ' + arTables[N]);
          try
            ExecSQL;
          finally
            Free;
            qry := nil;
          end;
        end;
      end;
  finally
    lst.Free;
  end; { try/finally }
end;

Псевдокод для этого довольно прост.

  1. Получите список всех таблиц в базе данных SQL Server, переданной в процедуру.

  2. Получите имя таблицы из массива имен таблиц.

  3. Если переданное имя таблицы окажется в списке таблиц, полученных из базы данных, УДАЛИТЬ его.

  4. Повторяйте шаги 2 и 3, пока не будут исчерпаны все имена таблиц.

Причина, по которой я провожу сравнение на шаге 3, заключается в том, что если вы выдадите DROP к несуществующей таблице, SQL Server выдаст исключение. Эта методология полностью позволяет избежать этой проблемы.

Ниже приведено подробное описание параметров.

Ses var TSession
это переменная экземпляра сеанса, которую вы передаете в процедуру по ссылке. Примечание.
Перед использованием НЕОБХОДИМО создать экземпляр. Процедура не создает экземпляр. Предполагается, что он уже существует. Это особенно необходимо при использовании этой процедуры внутри потока. Но если вы не создаете многопоточное приложение, вы можете использовать переменную сеанса по умолчанию.
DBName String
Имя клиентской базы данных MS SQL Server.
ArTables Array of String
это открытый массив строк что вы можете перейти в процедуру. Это означает, что вы можете пройти любой размер массива, и процедура обработает его. Например, в В основной программе создания таблиц я определяю массив следующим образом:
    arPat[0] := 'dbo.Temp0';
    arPat[1] := 'dbo.Temp1';
    arPat[2] := 'dbo.Temp2';
    arPat[3] := 'dbo.Temp3';
    arPat[4] := 'dbo.Temp4';
    arPat[5] := 'dbo.Temp5';
    arPat[6] := 'dbo.PatList';
    arPat[7] := 'dbo.PatientList';
    arPat[8] := 'dbo.EpiList';
    arPat[9] := 'dbo.' + FDisease + 'CrossTbl_' + FQtrYr;
    arPat[10] := 'dbo.' + FDisease + 'Primary_' + FQtrYr;

и передать его в процедуру.
StatMsg TStatusMsg
Это процедурный тип : procedure(Msg : String). Вы не можете использовать метод класса для этой процедуры; вместо этого вы объявляете обычную процедуру, которая ссылается на обычную процедуру. Например, я объявляю процедуру уровня интерфейса под названием StatMsg, которая ссылается на переменную экземпляра потока и метод следующим образом:
    procedure StatMsg(Msg: string); 
    begin
      thr.FStatMsg := Msg;
      thr.Synchronize(thr.UpdateStatus); 
    end;

Хитрость здесь в том, что «thr» — это переменная экземпляра, используемая для создания экземпляра моего класса потока. Переменная экземпляра находится в основной форме моего приложения. Это означает, что его тоже необходимо объявить как переменную интерфейса.

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

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

Previous page:
Вернуть строку в DOS-кодировке
Top:
DRKB
Next page:
Пример вызова динамического SQL с возвращаемой переменной