怎么样从一条未知的SQL语句取出这条SQL语句中的FROM表名.并确定语句中有哪些字段是属于这个表,急!!!求救

解决方案 »

  1.   

    unit provider.pas
    procedure TSQLResolver.InitTreeData(Tree: TUpdateTree);
    begin
      ....
      TableName := VarToStr(Tree.Delta.GetOptionalParam(szTABLE_NAME));
      if TableName = '' then
        TableName := <font color=red>IProviderSupport(Tree.Source).PSGetTableName</font>;
      Provider.DoGetTableName(Tree.Source, TableName);
      if TableName <> '' then
        Info.QuotedTable := GetQuotedTableName(Info.IsSQLBased, Info.QuoteChar, TableName);
      ....
    end;这一段就是TSQLResolver确定目标表的代码,其中Tree.Source定义为TDataSet,
    估计就等于TDataSetProvider.DataSet,我们这里是一个TQuery
    在DBTables.pas中可以看到TQuery.PSGetTableName方法如下:
    function TQuery.PSGetTableName: string;
    begin
      Result := GetTableNameFromSQL(SQL.Text);
    end;
    其中GetTableNameFromSQL定义在DBCommon.pas中,各位,这下发现宝贝了!!!!
    这个单元里包括一些SQL语法分析程序,定义相当完备,
    比如这个GetTableNameFromSQL函数分析一段SQL语句的目标表名,
    只用了20行就搞定了,是不是很厉害??
      

  2.   

    pos()
    copy()
    用这些函数对语句加以分析就可以了呀
      

  3.   

    同意楼上,先定位from,再拷贝后面的字符串
      

  4.   

    没有太好的办法,截取FROM 后面的子串,然后在根据WHERE/ORDER BY /GROUP BY 等关键字来分析
      

  5.   

    function GetTableNameFromSQL(const SQL: string): string;
    var
      Start: PChar;
      Token: string;
      SQLToken, CurSection: TSQLToken;
    begin
      Result := '';
      Start := PChar(SQL);
      CurSection := stUnknown;
      repeat
        SQLToken := NextSQLToken(Start, Token, CurSection);
        if SQLToken in SQLSections then CurSection := SQLToken;
      until SQLToken in [stEnd, stFrom];
      if SQLToken = stFrom then
      begin
        repeat
          SQLToken := NextSQLToken(Start, Token, CurSection);
          if SQLToken in SQLSections then
            CurSection := SQLToken else
          // stValue is returned if TableNames contain quote chars.
          if (SQLToken = stTableName) or (SQLToken = stValue) then
          begin
            Result := Token;
            while (Start[0] = '.') and not (SQLToken in [stEnd]) do
            begin
              SQLToken := NextSqlToken(Start, Token, CurSection);
              Result := Result + '.' + Token;
            end;
            Exit;
          end;
        until (CurSection <> stFrom) or (SQLToken in [stEnd, stTableName]);
      end;
    end;
    这个函数真的写得很巧妙