:: 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;
|
При использовании материала - ссылка на сайт обязательна
|
|