Еще одна мысль: Microsoft предоставляет Visual Studio сборку, которая может анализировать SQL. Я использовал его, и он довольно прост в использовании. Вы можете использовать его для анализа текста ваших хранимых процедур; он может вернуть список различных токенов в ваших утверждениях, включая тип токена. Таким образом, он должен помочь вам отличить текстовую строку, которая вас может заинтересовать, от части комментария, которую можно игнорировать. Подробнее здесь: http://blogs.msdn.com/b/gertd/archive/2008/08/21/getting-to-the-crown-jewels.aspx.
По сути, из .NET вы открываете соединение с вашей базой данных и запрашиваете системные комментарии для текста ваших хранимых процедур. Вы будете проходить через каждую процедуру и анализировать ее, используя эти парсеры. Затем вы должны использовать Sql100ScriptGenerator для извлечения токенов из проанализированного текста, просмотра циклов и поиска токенов, типы которых являются строковыми литералами ASCII или Unicode. Для этих строк проверьте их длину, чтобы увидеть, не превышает ли она 20, и, если это так, пометьте строки и процы как требующие дальнейшего рассмотрения.
Я немного поиграл с этим, и вот очень грубый пример, иллюстрирующий основной принцип:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Data.Schema;
using Microsoft.Data.Schema.ScriptDom;
using Microsoft.Data.Schema.ScriptDom.Sql;
namespace FindHardCodedStrings
{
class Program
{
static void Main(string[] args)
{
using (SqlConnection conn = new SqlConnection())
{
SqlConnectionStringBuilder bldr = new SqlConnectionStringBuilder();
bldr.DataSource = "localhost\\sqlexpress";
bldr.InitialCatalog = "msdb";
bldr.IntegratedSecurity = true;
conn.ConnectionString = bldr.ConnectionString;
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "select [text] from syscomments";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
TSql100Parser parser = new TSql100Parser(false);
Sql100ScriptGenerator gen = new Sql100ScriptGenerator();
gen.Options.SqlVersion = SqlVersion.Sql100;
foreach (DataRow proc in ds.Tables[0].Rows)
{
string txt = proc[0].ToString();
using (System.IO.TextReader sr = new System.IO.StringReader(txt))
{
IList<ParseError> errs;
IScriptFragment frag = parser.Parse(sr, out errs);
if (null == frag)
continue;
IList<TSqlParserToken> tokens = gen.GenerateTokens((TSqlFragment)frag);
foreach (TSqlParserToken token in tokens)
{
if (token.TokenType == TSqlTokenType.UnicodeStringLiteral || token.TokenType == TSqlTokenType.AsciiStringLiteral)
{
if (token.Text.Length >= 20)
Console.WriteLine("String found: " + token.Text);
}
}
}
}
}
}
}
}