【发布时间】:2011-01-09 23:43:22
【问题描述】:
我们在 ANSI_NULLS 设置和计算列方面存在一些问题,并且我们有大量的存储过程具有
SET ANSI_NULLS OFF
我们想把它们全部改成
SET ANSI_NULLS ON
有没有一种简单的方法可以做到这一点,或者我必须将所有 SP 提取到一个脚本中,更改它并再次运行它以删除并重新创建所有 SPa
【问题讨论】:
标签: sql-server stored-procedures
我们在 ANSI_NULLS 设置和计算列方面存在一些问题,并且我们有大量的存储过程具有
SET ANSI_NULLS OFF
我们想把它们全部改成
SET ANSI_NULLS ON
有没有一种简单的方法可以做到这一点,或者我必须将所有 SP 提取到一个脚本中,更改它并再次运行它以删除并重新创建所有 SPa
【问题讨论】:
标签: sql-server stored-procedures
只是想在那里发出警告。我无法想象为什么您为所有 SP 设置了 ansi_nulls,但是如果他们中的任何一个以任何方式依赖与 NULL 的比较(并且可能发生很多不同的方式),当您更改时,您的结果会有所不同那个设置。我建议在安全的环境中进行一些严格的回归测试。
【讨论】:
您必须编写所有过程的脚本,并在启用 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 的代码
但通常我只会使用 Enterprise Manager,从存储过程列表的顶部开始:
我的剪贴板包含的位置:
SET ANSI_NULLS ON
GO
如果你不幸被 SSMS 卡住了,那么你就是那个 POS 的 SOL,IIRC。 TWSS。
【讨论】:
我们使用的解决方案是 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; }
}
}
【讨论】:
到目前为止,最简单的方法是编写 s'procs 脚本,运行查找和替换命令,然后再次运行 proc 定义。
【讨论】: