C# 存储过程解析器
我正试图解析数百个存储过程,专门获取它们的输出变量“@FirstName”,它们使用哪些表,以及从“MyTbl.FirstName”中提取哪些字段。我可以很容易地收集变量,但是收集表名时遇到了问题。有人能帮忙吗C# 存储过程解析器,c#,sql-server-2005,stored-procedures,text-parsing,sql-parser,C#,Sql Server 2005,Stored Procedures,Text Parsing,Sql Parser,我正试图解析数百个存储过程,专门获取它们的输出变量“@FirstName”,它们使用哪些表,以及从“MyTbl.FirstName”中提取哪些字段。我可以很容易地收集变量,但是收集表名时遇到了问题。有人能帮忙吗 keyColl = tables.Keys; foreach (string var in keyColl) { if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Conta
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
到目前为止,我已经能够通过使用StreamReader解析SQL文件并逐行收集信息来提取大多数字段,例如,如果一行包含输出,那么我知道该行中的第一个文本很可能是@Variable
@Address1 varchar(45) output,
@Address2 varchar(45) output,
@City varchar(35) output,
@State varchar(2) output,
@Zip varchar(10) output
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
从那里,我可以将@Variable存储到字典中,如果任何一行包含@Variable,并且还包含一个“=”,那么我知道它对应于哪个字段
@Address1 = c.Address,
@Address2 = c.AddressSecondLine,
@City = c.City,
@State = c.State,
@Zip = c.ZipOrPostalCode
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
现在我在收集表名时遇到了一些问题。我可以轻松地从字段名中解析表别名,但在将别名与表名匹配时遇到问题。有人知道这样做的好方法吗?以下是我到目前为止一直在尝试的:
FROM Table.dbo.SalesStuff ss
LEFT OUTER JOIN Table.dbo.Customer c ON ss.CustNo = c.CustNo
Left JOIN Table.dbo.Vending v on @tmpVin = v.vin
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
代码:
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
我认为这会匹配表别名,因为大多数别名都是字母,后跟换行符,但到目前为止,我还没有得到任何表名。。。有人有主意吗?你可以用。例如,对于类似字符串的
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
FROM Table.dbo.SalesStuff ss
你可以用
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
string pattern = @"\s*FROM\s+Table\.dbo\.(\w+)\s+(\w+)";
string input = "line from stored proc body here";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine("table name: {0}", match.Groups[1].Value);
Console.WriteLine("Alias: {0}", match.Groups[2].Value);
Console.WriteLine();
}
您必须为包含表名和别名的每种类型的字符串定义模式。坦率地说,我认为您的解析想法不会走得太远。您对如何在每个过程中格式化代码做出了非常大胆的假设。我对格式化非常仔细,但我无法保证您在这么多过程中所依赖的一致性,即使我自己编写了它们
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
需要注意的是,延迟的名称解析可能会影响您,而且依赖项跟踪在SQLServer2005()中肯定远不是完美的,这里有几个想法(它们也不是完美的,但它们肯定会减少头发的灰白):
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
sys.parameters
,可以以比暴力解析更简单的方式获取参数:
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
选择对象名称([OBJECT\u id])、p.NAME、t.NAME
从sys.parameters作为p
内部联接sys.types为t
在p.system\u type\u id=t.system\u type\u id上
其中p.is_输出=1;
sys.sql\u dependencies
中获取表名和列名,但是这将包括where/join子句中引用的列,即使它们不在select列表中:
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
选择[procedure]=OBJECT\u NAME(d.[OBJECT\u id]),
[表]=对象名称(d.参考的主要id),
[列]=c.name
从sys.sql\u依赖项中选择d
将sys.columns内部连接为c
在c.[object\u id]=d.referenced\u major\u id上
c.列id=d.引用的次要id;
的列,它被选中了
,但我没有发现它是准确/可靠的
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}
请注意,在动态SQL中发生的任何事情都将保留在动态SQL中—因此,如果您的过程使用动态SQL,则几乎不可能剔除表/列名。如果不知道
keyColl
或line
中的实际内容,甚至看不到您在查询行中迭代的位置,就很难分辨。调试器认为您在比较什么?遗憾的是,我认为在每个查询中依赖单字母别名后跟回车是不安全的。。。
keyColl = tables.Keys;
foreach (string var in keyColl)
{
if (line.Contains(" " + var + '\r') || line.Contains(" " + var + " ") || line.Contains(" " + var + ((char)13)) || line.Contains(" " + var + Environment.NewLine))
{
tables[var] = line.ToString();
break;
}
}