我还要补充一点,表达式的“规范化”有时不仅会添加括号,还会以非常不同的方式改变一些表达式!
例如,在 MS SQL 2008 Express 中,我使用以下表达式创建了一个默认值:
year(getdate()) + 1
但 SQL Server 将其更改为
(datepart(year,getdate())+(1))
所以,我不相信任何一种规则或正则表达式都能100%解决你的问题,所以我建议你结合几种方法
1)首先,我认为在您的情况下,典型的约束数量有限,通常存在于大多数数据库中。通常,有 getdate() 和常量数值表达式 (0)、(1)。您可以拥有一个包含这些典型约束的表格,这些约束将帮助您匹配预期表达式和实际表达式。
2)然后您可以尝试非常简单的规则,将所有字段名称包含在 [] 括号中,并将所有常量和数学运算包含在 () 中,因此您将year + 1转换为([year] + (1))。我想这可以用正则表达式来完成。
3) 对于无法使用第一种或第二种方法比较预期结果和实际结果的所有情况,您将按照您的建议进行 - 创建一个临时表并比较结果。
编辑 04.Aug:
我发现当您创建数据库级默认值时,它们不会被规范化。奇怪,嗯?但是可能,您可以使用这个事实并创建绑定到列的数据库级默认值,而不是为列创建默认约束(不过,我认为这将是设计上的一个非常大的变化,并且需要对现有数据库进行大量更新)
至于列默认约束,以及动态创建/删除默认值以获得规范化形式的方法,这里是一个使用 Microsoft.SqlServer.Management.Smo 库的简单 C# 代码。我建议创建一个包含 IntTest int、VarcharTest varchar(1)、DateTimeTest datetime 等列的 test_table - 即每种类型只有一列。在这种情况下,您将创建/删除默认值,但不必创建删除表和列,这将提高性能。
将遵循 C# 代码(包括使用 Microsoft.SqlServer.Management.Smo;)
Server server = new Server("localhost\\SQLEXPRESS");
Database db = server.Databases["test"];
Table t = db.Tables["test_defaults"];
//here should be some logic to select column name depending on default data type
//for example for DateTime defaults we will use "DateTimeTest" column
Column c = t.Columns["DateTimeTest"];
//clean up previous results if they exist
DefaultConstraint constr = c.DefaultConstraint;
if (constr != null) constr.Drop();
//create new constraint
constr = c.AddDefaultConstraint();
constr.Text = "getdate()";
constr.Create();
//after refresh we will have a new text
constr.Refresh();
string result = constr.Text;
//drop it if we don't need it
constr.Drop();