Как лучше всего найти жестко запрограммированные строки английского языка в хранимых процедурах SQL Server? - PullRequest
1 голос
/ 23 февраля 2011

Мы работаем над тем, чтобы сделать наше приложение на 100% локализуемым, и мы в основном там.Однако иногда мы находим английскую строку, все еще жестко запрограммированную в хранимых процедурах.(Между прочим, мы работаем на SQL Server 2005.) У нас есть тысячи хранимых процедур, поэтому выполнять их вручную нецелесообразно.Я пытаюсь придумать наиболее точные способы автоматизации поиска.

Теперь я знаю, что нет средств для поиска «английских» строк - кроме поиска строк, ограниченных одинарными кавычками и, возможно, 20+ символамидолго следует смывать большинство из них.Теперь достаточно для наших целей.Но я также ожидаю много ложных срабатываний в комментариях к хранимым процедурам.

Так как бы вы подошли к этому?Позволит ли SMO ​​дразнить SQL в хранимой процедуре и комментарии в нем?Должен ли я использовать OBJECT_DEFINITION () и начать взламывать некоторые ужасающие регулярные выражения?

Заранее благодарны, ребята.

Ответы [ 2 ]

4 голосов
/ 23 февраля 2011

Еще одна мысль: 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);
                            }
                        }
                    }
                }

            }
        }
    }
}
2 голосов
/ 23 февраля 2011

Мы решили проблему, вытекающую из этого, создав SQL-серверы с различными настройками языка / региона и запустив наши sp, отметив, какие из них сломались.

Возможно, это не самое элегантное решение, но мы смогли это сделатьэто быстро из-за ограниченных различных настроек местности, которые мы поддерживаем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...