2011-06-09 83 views
10

我正在尋找一個很好的SQL解析器在Delphi(2010)for SQL Server中。我需要這樣的東西來解析查詢並提取:select列表,where和order by子句。無論它是商業還是開源解決方案都無關緊要。它也可以是一個DLL(當然,用任何語言編寫),但我更喜歡VCL組件通過DLL。SQL中的SQL解析器

+0

不完全一樣的問題,但可能是值得一試:ttp://stackoverflow.com/questions/615608/need-in-sql-parser-on-delphi – 2011-06-09 23:01:53

+0

是的,但它是爲火鳥,而不是爲SQL服務器。它們之間有差異。 – 2011-06-09 23:03:10

+1

使用cte,嵌套查詢,插入/刪除/更新/改變/等語句,這是非平凡的代碼。真正解決sql server查詢的唯一安全方法是使用sql server。 – 2011-06-10 00:02:59

回答

10

拉斐爾的Delphi自帶地處DBCommon單元

檢查這些功能

function NextSQLToken(var p: PAnsiChar; out Token: AnsiString; CurSection: TSQLToken): TSQLToken; overload; 
function NextSQLToken(var p: PWideChar; out Token: WideString; CurSection: TSQLToken): TSQLToken; overload; 
function NextSQLToken(var p: PChar; out Token: String; CurSection: TSQLToken): TSQLToken; overload; 

function GetIndexForOrderBy(const SQL: WideString; DataSet: TDataSet): TIndexDef; 
function GetTableNameFromSQL(const SQL: WideString): WideString; 
function GetTableNameFromQuery(const SQL: Widestring): Widestring; 
function AddParamSQLForDetail(Params: TParams; SQL: WideString; Native: Boolean; QuoteChar: WideString = ''): WideString; 
function IsMultiTableQuery(const SQL: WideString): Boolean; 
function SQLRequiresParams(const SQL: WideString): Boolean; 

function NextSQLTokenEx(var p: PWideChar; out Token: UnicodeString; CurSection: TSQLToken; IdOption: IDENTIFIEROption): TSQLToken; overload; 
function NextSQLTokenEx(var p: PWideChar; out Token: WideString; CurSection: TSQLToken; IdOption: IDENTIFIEROption): TSQLToken; overload; 
function NextSQLTokenEx(var p: PAnsiChar; out Token: AnsiString; CurSection: TSQLToken; IdOption: IDENTIFIEROption): TSQLToken; overload; 
function GetTableNameFromSQLEx(const SQL: WideString; IdOption: IDENTIFIEROption): WideString; 

這是一個非常簡單的示例來說明如何解析SQL語句並獲取所有元素的SQL語法分析程序。

uses 
    TypInfo, 
    DbCommon, 
    SysUtils; 


const 
    StrSql ='Select Field1, Field2, 54 field3, Field4 from Mytable1 Order by Field1,Field5'; 

procedure ParseSql(Const Sql : string); 
var 
    SQLToken  : TSQLToken; 
    CurSection : TSQLToken; 
    Start  : PWideChar; 
    Token  : WideString; 
    IdOption  : IDENTIFIEROption; 
begin 
    IdOption :=idMixCase; 
    Start  :=PWideChar(StrSql); 
    CurSection := stUnknown; 
    repeat 
    SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption); 
    if SQLToken<>stEnd then 
    Writeln(Format('Type %s Token %s', [GetEnumName(TypeInfo(TSQLToken), integer(SQLToken)),Token])); 
    CurSection := SQLToken; 
    until SQLToken in [stEnd]; 
end; 



begin 
    try 
    ParseSql(StrSql); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 

這將返回

Type stSelect Token Select 
Type stFieldName Token Field1 
Type stFieldName Token Field2 
Type stNumber Token 54 
Type stFieldName Token field3 
Type stFieldName Token Field4 
Type stFrom Token from 
Type stTableName Token Mytable1 
Type stOrderBy Token Order by 
Type stFieldName Token Field1 
Type stFieldName Token Field5 
+0

它確實不錯,但它認爲'TOP'是一個領域,但它當然不是。 – 2011-06-10 14:12:36

+0

就像我說的那樣效果不好。它在很多情況下都失敗了,比如當你有'Table.Field'的時候,它將字段和字段作爲字段返回。它不能檢測到Count(),Sum(),Average和Top。對於我所尋找的不夠好,但感謝您的幫助。 – 2011-06-10 14:34:17

+1

@Rafael對不起,我會保留我的答案,因爲可以幫助您在未來解析簡單的sql語句。另一種選擇是建立你自己的解析器(DbCommon),並閱讀這樣的文章http://www.felix-colibri.com/papers/db/sql_parser/sql_parser.html – RRUZ 2011-06-10 14:45:00