更改数据库中所有存储过程的ANSI_NULLS设置

时间:2010-01-27 14:16:30

标签: sql-server stored-procedures

我们在ANSI_NULLS设置和计算列方面存在一些问题,我们有大量的存储过程

SET ANSI_NULLS OFF

我们希望将它们全部更改为

SET ANSI_NULLS ON

是否有一种简单的方法可以做到这一点,或者我必须将所有SP提取到脚本中,更改它并再次运行它以删除并重新创建所有SPa

4 个答案:

答案 0 :(得分:4)

您必须编写所有过程的脚本,然后使用ANSI_NULLS重新创建它们。

如果我有很多要做,我可能会在我的客户端应用中添加一个功能。

伪代码:

procedure FixAllStoredProcedureAnsiNullness(connection)
{
   Strings spNames = GetStoredProcedureNames(connection);

   foreach spName in spNames
   {
       String sql = GetStoredProcedureSQL(connection, spName);

       //turn on option for remainder of connection
       connection.ExecuteNoRecords("SET ANSI_NULLS ON"); 

       BeginTransaction(connection);
       try
          connection.ExecuteNoRecords("DROP PROCEDURE "+spName);
          connection.ExecuteNoRecords(sql);
          CommitTranasction(connection);
       except
          RollbackTransaction(connection);
          raise;
       end;
   }
}

我有关于如何在SQL Server: How to generate object scripts without DMO/SMO?

上以编程方式获取存储过程的SQL的代码

但通常我只会使用企业管理器,从存储过程列表的顶部开始:

  1. 返回
  2. 控制 + 主页
  3. 控制 + V
  4. 点击确定
  5. 向下
  6. 转到1
  7. 我的剪贴板包含:

    SET ANSI_NULLS ON
    GO
    

    如果你不幸被SSMS困住,那么你就是那个POS,IIRC的SOL。 TWSS。

答案 1 :(得分:3)

我们使用的解决方案是由 Ian 发布的,现在我们有一个自动程序来解决问题。

以下是我们用于从数据库重新创建所有SP的最终代码:

public static class AnsiNullsManager
{

    public static void ReCreateAllStoredProcedures(SqlConnection connection, bool ansiNullsOn)
    {
        var sql =
            @"select object_name(sys.all_sql_modules.object_id) as Name, definition as Code
                from sys.all_sql_modules inner join sys.objects ON 
                sys.all_sql_modules.object_id = sys.objects.object_id
                where objectproperty(sys.all_sql_modules.object_id, 'IsProcedure') = 1 AND is_ms_shipped = 0 and uses_ansi_nulls = " +
            (ansiNullsOn ? "0" : "1") +
            "ORDER BY Name ";

        if (connection.State == ConnectionState.Closed)
            connection.Open();

        var sps = new List<SpObject>();

        var cmd = connection.CreateCommand();
        cmd.CommandText = sql;

        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                sps.Add(new SpObject(reader.GetString(0), reader.GetString(1)));
            }
        }

        var cmdSetAnsiNulls = connection.CreateCommand();
        cmdSetAnsiNulls.CommandText = "SET ANSI_NULLS " + (ansiNullsOn ? "ON" : "OFF") + ";";
        cmdSetAnsiNulls.ExecuteNonQuery();

        foreach (var sp in sps)
        {
            var trans = connection.BeginTransaction();

            try
            {

                var cmdDrop = connection.CreateCommand();
                cmdDrop.CommandText = "DROP PROCEDURE " + sp.Name;
                cmdDrop.Transaction = trans;
                cmdDrop.ExecuteNonQuery();



                var cmdReCreate = connection.CreateCommand();
                cmdReCreate.CommandText = sp.Code;
                cmdReCreate.Transaction = trans;
                cmdReCreate.ExecuteNonQuery();
                trans.Commit();

            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
        }

    }

    private class SpObject
    {
        public SpObject(string name, string code)
        {
            Name = name;
            Code = code;
        }

        public string Name { get; private set; }
        public string Code { get; private set; }
    }

}

答案 2 :(得分:2)

只想在那里发出警告。我无法想象为什么你的所有SP都启动了ansi_nulls,但是如果他们中的任何一个指望以任何方式与NULL进行比较(并且可能会有很多不同的方式),那么当你改变时你的结果会有所不同那个设定。我建议在安全的环境中进行一些严格的回归测试。

答案 3 :(得分:1)

到目前为止,最简单的方法是编写s'procs脚本,运行find和replace命令,然后再次运行proc定义。