【问题标题】:How best to find hard-coded English language strings in SQL Server stored procedures?如何最好地在 SQL Server 存储过程中找到硬编码的英语语言字符串?
【发布时间】:2011-07-02 09:10:52
【问题描述】:

我们正在努力使我们的应用程序 100% 可本地化,而且我们大部分时间都在那里。但是,我们偶尔会在存储过程中发现仍然硬编码的英文字符串。 (顺便说一下,我们使用的是 SQL Server 2005。)我们有数千个存储过程,因此手动处理它们是不切实际的。我正在尝试寻找最准确的自动搜索方法。

现在,我知道没有办法搜索“英语”字符串 - 但搜索以单引号为界且长度可能超过 20 个字符的字符串应该会将大部分字符串清除。现在对我们的目的来说已经足够好了。但我预计存储过程的 cmets 也会出现很多误报。

那么您将如何处理这个问题? SMO 会让我将存储过程中的 SQL 与其中的 cmets 区分开来吗?我是否必须使用 OBJECT_DEFINITION() 并开始破解一些可怕的正则表达式?

提前非常感谢,伙计们。

【问题讨论】:

    标签: sql sql-server-2005 stored-procedures localization


    【解决方案1】:

    另一个想法:微软通过 Visual Studio 提供了一个可以解析 SQL 的程序集。我用过它,而且使用起来相当简单。您也许可以使用它来解析存储过程的文本;它可以返回语句中各种标记的列表,包括标记的类型。因此,它应该能够帮助您区分什么是您可能感兴趣的文本字符串与什么是评论的一部分并且可以被忽略。这里有更多细节:http://blogs.msdn.com/b/gertd/archive/2008/08/21/getting-to-the-crown-jewels.aspx

    基本上,在 .NET 中,您将打开与数据库的连接并查询 syscmets 以获取存储过程的文本。您将遍历每个过程并使用这些解析器对其进行解析。然后,您将使用 Sql100ScriptGenerator 从解析的文本中获取标记,循环遍历标记并查找类型为 ASCII 或 Unicode 字符串文字的标记。对于这些字符串,检查它们的长度是否超过 20,如果是,将字符串和 proc 标记为需要进一步审查。

    我玩了一下,这里有一个 非常 原始示例来说明基本原理:

    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);
                                }
                            }
                        }
                    }
    
                }
            }
        }
    }
    

    【讨论】:

    • 非常好!谢谢你。我要试试这个。我有一些直觉认为这是可能的,你的想法让我更接近
    • 试一试,效果很好。即使是你非常原始的代码也让我完成了 98% 的工作。它得到了很多误报,但这就是我所期待的。当我扫描结果时,英语短语非常清晰。
    【解决方案2】:

    我们通过在不同的语言/区域设置中创建 SQL Server 并运行我们的 sp 解决了由此产生的问题,并记录了哪些出现故障。

    这可能不是最优雅的解决方案,但由于我们支持的不同位置设置有限,我们能够快速完成。

    【讨论】:

    • 有趣的想法。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    相关资源
    最近更新 更多