2

何百ものストアド プロシージャを解析して、出力変数「@FirstName」、使用するテーブル、および「MyTbl.FirstName」から取得するフィールドを具体的に取得しようとしています。変数はかなり簡単に収集できますが、テーブル名の収集に問題があります。誰でも助けてもらえますか?

これまでのところ、StreamReader を使用して SQL ファイルを解析し、行ごとに情報を収集することで、これらのフィールドのほとんどを引き出すことができました。たとえば、行に出力が含まれている場合、行の最初のテキストがおそらく@変数。

@Address1 varchar(45) output,
@Address2 varchar(45) output,
@City varchar(35) output,
@State varchar(2) output,
@Zip varchar(10) output

そこから @Variable をディクショナリに保存できます。行に @Variable が含まれていて、「=」も含まれている場合は、対応するフィールドが一致していることがわかります。

@Address1 = c.Address,          
@Address2 = c.AddressSecondLine,
@City = c.City,
@State = c.State,
@Zip = c.ZipOrPostalCode

今、テーブル名の収集に問題があります。フィールド名からテーブル エイリアスを簡単に解析できますが、エイリアスとテーブル名の一致に問題があります。これを行う良い方法を知っている人はいますか?これが私がこれまで試してきたことです:

FROM Table.dbo.SalesStuff ss
LEFT OUTER JOIN Table.dbo.Customer c ON ss.CustNo = c.CustNo
Left JOIN Table.dbo.Vending v on @tmpVin = v.vin

コード:

keyColl = tables.Keys;
foreach (string var in keyColl)
{
    if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
    {
        tables[var] = line.ToString();
        break;
    }    
}

ほとんどのエイリアスは文字の後に改行が続くため、これはテーブルのエイリアスと一致すると思いましたが、これまでのところ、テーブル名を取得できませんでした...誰かアイデアがありますか?

4

2 に答える 2

6

率直に言って、あなたの構文解析のアイデアはあまり進展しないと思います。コードがすべての手順でどのようにフォーマットされるかについて、非常に勇敢な仮定をしています。私は書式設定について非常に細心の注意を払っていますが、すべて自分で作成したとしても、多くの手順にわたって一貫性を保証することはできません.

延期された名前解決は背後で噛み付く可能性があり、依存関係の追跡は SQL Server 2005 では完全にはほど遠いものでした ( SQL Server 2008 でも正確さを保つために私が投稿した回避策を参照してください)。どちらも完璧ではありませんが、間違いなく白髪が少なくなります):

  1. カタログ ビューを使用すると、総当たり解析よりもはるかに簡単な方法でパラメーターを取得できますsys.parameters

     SELECT OBJECT_NAME([object_id]), p.name, t.name
       FROM sys.parameters AS p
       INNER JOIN sys.types AS t
       ON p.system_type_id = t.system_type_id
       WHERE p.is_output = 1;
    
  2. すべてのプロシージャが再コンパイルされ、名前解決の遅延の問題が発生していない場合は、テーブル名と列名を取得できsys.sql_dependenciesます。リスト:

     SELECT [procedure] = OBJECT_NAME(d.[object_id]),
       [table] = OBJECT_NAME(d.referenced_major_id),
       [column] = c.name
       FROM sys.sql_dependencies AS d
       INNER JOIN sys.columns AS c
       ON c.[object_id] = d.referenced_major_id
       AND c.column_id = d.referenced_minor_id;
    

ここに呼ばれるコラムがありますが、is_selected正確/信頼できるとは思いませんでした.

動的 SQL で発生することはすべて動的 SQL にとどまることに注意してください。したがって、プロシージャで動的 SQL を使用する場合、テーブル/列名を選別することはほぼ不可能になります。

于 2013-04-04T00:23:02.267 に答える
0

正規表現を使用できます。たとえば、次のような文字列の場合

FROM Table.dbo.SalesStuff ss

あなたが使用することができます

  string pattern = @"\s*FROM\s+Table\.dbo\.(\w+)\s+(\w+)";
  string input = "line from stored proc body here";
  MatchCollection matches = Regex.Matches(input, pattern);

  foreach (Match match in matches)
  {
     Console.WriteLine("table name:       {0}", match.Groups[1].Value);
     Console.WriteLine("Alias:            {0}", match.Groups[2].Value);
     Console.WriteLine();
  }

テーブル名とエイリアスを含む文字列のタイプごとにパターンを定義する必要があります。

于 2013-04-04T00:19:21.803 に答える