Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 存储过程解析器_C#_Sql Server 2005_Stored Procedures_Text Parsing_Sql Parser - Fatal编程技术网

C# 存储过程解析器

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

我正试图解析数百个存储过程,专门获取它们的输出变量“@FirstName”,它们使用哪些表,以及从“MyTbl.FirstName”中提取哪些字段。我可以很容易地收集变量,但是收集表名时遇到了问题。有人能帮忙吗

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;
        }    
    }