生成SQL Server数据库模式哈希的脚本的最快方法是什么?

4
我想获取整个数据库的SQL模式,然后生成一个哈希值。这样我就可以检查回滚脚本是否将模式返回到原始状态。是否有我可以使用的存储过程或其他巧妙方法?我希望它尽可能快。

1: 2005/2008 2: 不是的 3: 那是针对V2版本的 :) - mcintyre321
3个回答

2

如果您将表和键与代码和约束分开,则可以轻松地对后者进行哈希。

SELECT
    CHECKSUM_AGG(BINARY_CHECKSUM (*))
FROM   
    (SELECT
        definition 
    FROM
        sys.default_constraints
    UNION ALL
    SELECT
        definition 
    FROM
        sys.sql_modules
    UNION ALL
    SELECT
        definition 
    FROM
        sys.check_constraints
    ) foo

我需要表、存储过程、约束等所有内容的哈希值,我很担心! - mcintyre321
那么不完整的答案就是-1吗?既然你已经写了一个工具https://dev59.com/qHVD5IYBdhLWcg3wWaRh#541419,为什么还要问这个问题呢? - gbn

2
以下内容应该有效:
        Microsoft.SqlServer.Management.Smo.Server srv = new Microsoft.SqlServer.Management.Smo.Server("Server");

        Microsoft.SqlServer.Management.Smo.Database db = srv.Databases["DB_Name"];

        // Set scripting options as needed using a ScriptingOptions object.
        Microsoft.SqlServer.Management.Smo.ScriptingOptions so = new ScriptingOptions();
        so.AllowSystemObjects = false;
        so.ScriptDrops = false;
        so.Indexes = true;
        so.ClusteredIndexes = true;
        so.PrimaryObject = true;
        so.SchemaQualify = true;
        so.IncludeIfNotExists = false;
        so.Triggers = true;

        System.Collections.Specialized.StringCollection sc = new System.Collections.Specialized.StringCollection();
        StringBuilder sb = new StringBuilder();

        foreach (Table item in db.Tables)
            if (!item.IsSystemObject)
            {
                sc = item.Script(so);
                foreach (string s in sc)
                    sb.Append(s);
            }

        foreach (StoredProcedure item in db.StoredProcedures)
            if (!item.IsSystemObject)
                if (!item.IsSystemObject)
                {
                    sc = item.Script(so);
                    foreach (string s in sc)
                        sb.Append(s);
                }

        foreach (UserDefinedFunction item in db.UserDefinedFunctions)
            if (!item.IsSystemObject)
                if (!item.IsSystemObject)
                {
                    sc = item.Script(so);
                    foreach (string s in sc)
                        sb.Append(s);
                }

        foreach (Trigger item in db.Triggers)
            if (!item.IsSystemObject)
                if (!item.IsSystemObject)
                {
                    sc = item.Script(so);
                    foreach (string s in sc)
                        sb.Append(s);
                }


        //sb.GetHashCode();
        // For a better hash do this.
        System.Security.Cryptography.MD5CryptoServiceProvider hashProvider = new System.Security.Cryptography.MD5CryptoServiceProvider();

        byte[] hashData = hashProvider.ComputeHash(ASCIIEncoding.ASCII.GetBytes(sb.ToString()));

抱歉,马特,我刚在LinqPad中尝试了一下。它似乎只是脚本化了数据库本身,而不是表模式或其他对象。此外,sb.GetHashCode()只是一个哈希值,我认为它仅适用于当前的AppDomain!它返回的是stringbuilder的内存位置,而不是其值的哈希,因此下次运行应用程序时,代码将不同。new StringBuilder("Hello").GetHashCode() != new StringBuilder("Hello").GetHashCode() - mcintyre321
你说得对。我以前也犯过同样的错误。或许这次我已经学会了。我已经编辑过代码了。希望现在更接近正确了。还有空格和确定需要哪些具体细节的问题,但这应该更接近正确了。 - Matt Spradley

0
我写了一个叫做SMOscript的工具,它使用SMO库调用来脚本化数据库中的所有对象。你可以使用它创建一个单独的.sql文件,并找到另一个工具在结果文件上计算哈希值。(例如随机谷歌出现了this

还不错。SMO 对我来说有点慢。可能会使用 OpenDbDiff 来做类似的事情,因为似乎没有人有一个我可以使用的单个 SP 调用。 - mcintyre321

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接