FAQ VCL
SQL

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика

Как распарсить SQL запрос?

uses
  Data.DBCommon,
  TypInfo;

const
  SQL = 'select * from (select * from dual) tbl';

procedure ParseSql(const Sql: string; TokenList: TStrings);
var
  SQLToken: TSQLToken;
  CurSection: TSQLToken;
  Start: PWideChar;
  Token: string;
  IdOption: IDENTIFIEROption;
begin
   IdOption := idMixCase;
   Start := PWideChar(Sql);
   CurSection := stUnknown;
   repeat
      SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption);
      if SQLToken <> stEnd then
         TokenList.Add(
            Format(
               'Type %s Token %s',
               [GetEnumName(TypeInfo(TSQLToken), Integer(SQLToken)), Token]
            )
         );
      CurSection := SQLToken;
   until SQLToken in [stEnd];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TokenList: TStrings;
begin
   TokenList := TStringList.Create;
   try
      ParseSql(SQL, TokenList);
      ShowMessage(TokenList.Text);
   finally
      TokenList.Free;
   end;
end;


Как извлечь имя первой таблицы из SQL запроса?

uses
  Data.DBCommon;

const
  SQL = 'select * from dual d';

procedure TForm1.Button1Click(Sender: TObject);
begin
   ShowMessage(GetTableNameFromSQL(SQL));
   // Обратите внимание на то, что извлекается именно
   // имя таблицы, а не ее псевдоним.
   // Если в запросе учавствует несколько таблиц,
   // извлечено будет лишь имя первой таблицы:
   // 'select d.*, t.* from dual d, tab t'.
   // С сложными вариантами этот метод не справится:
   // 'select * from (select * from dual) tbl',
   // 'select d.*, t.* from (select * from dual) d, tab t'.
   // А с этим запросом метод справится, и то только лишь
   // потому, что имя первой таблицы задано явно:
   // 'select d.*, t.* from dual d, (select * from tab) t'.   
end;


Как извлечь алиас первой таблицы из SQL запроса?

// Немного доработанная функция GetTableNameFromSQLEx из Data.DBCommon
function GetTableAliasFromSQLEx(const SQL: string; IdOption: IDENTIFIEROption): string;
var
  Start: PChar;
  Token: string;
  SQLToken, CurSection: TSQLToken;
begin
   Result := '';
   Start := PChar(SQL);
   CurSection := stUnknown;
   repeat
      SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption);
      if SQLToken in SQLSections then
         CurSection := SQLToken;
   until SQLToken in [stEnd, stFrom];
   if SQLToken = stFrom then
   begin
      repeat
         SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption);
         if SQLToken in SQLSections then
            CurSection := SQLToken else
         // stValue is returned if TableNames contain quote chars.
         if (SQLToken = stTableName) or (SQLToken = stValue) then
         begin
            if AnsiRightStr(Token, 1) = ';' then
               Token := AnsiLeftStr(Token, Token.Length-1);
            if AnsiRightStr(Token, 1) = ')' then
               Token := AnsiLeftStr(Token, Token.Length-1);

            while (Start[0] = '.') and not (SQLToken in [stEnd]) do
               SQLToken := NextSqlTokenEx(Start, Token, CurSection, IdOption);

            if Start[0] <> ',' then
            begin
               SQLToken := NextSqlTokenEx(Start, Token, CurSection, IdOption);
               while (SQLToken in [stTableName]) and not (SQLToken in [stEnd]) do
               begin
                   Result := Token;
                   if Start[0] = ',' then
                      Break;
                   SQLToken := NextSqlTokenEx(Start, Token, CurSection, IdOption);
               end;
            end;
            Exit;
         end;
      until (CurSection <> stFrom) or (SQLToken in [stEnd, stTableName]);
   end;
end;

function GetTableAliasFromSQL(const SQL: string): string;
begin
   Result := GetTableAliasFromSQLEx(SQL, idMixCase);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
   ShowMessage(GetTableAliasFromSQL('select * from dual d'));
end;


Как определить является ли SQL запрос мультитабличным?

uses
  Data.DBCommon;

const
//  SQL = 'select * from dual cross join dual';
  SQL = 'select * from dual d1 inner join dual d2 on d1.dummy = d2.dummy';

procedure TForm1.Button1Click(Sender: TObject);
begin
   if IsMultiTableQuery(SQL) then
      ShowMessage('Мультитабличный запрос');
   // А вот с union данный метод не справится:
   // 'select * from dual union select * from dual'.
end;


Как определить используются ли в запросе параметры (в секции WHERE)?

uses
  Data.DBCommon;

const
  SQL = 'select * from dual where dummy = ''DUMMY''';

procedure TForm1.Button1Click(Sender: TObject);
begin
   if SQLRequiresParams(SQL) then
      ShowMessage('Параметры используются');
   // Другими словами, присутствует секция where
end;

При использовании материала - ссылка на сайт обязательна