2014-03-06 145 views
-2

有沒有什麼辦法可以像下面的c#代碼那樣擁有存儲過程或函數:遞歸存儲過程或函數

我想將此方法轉換爲T-SQL。

public static IEnumerable<String> GetWords(Int32 length) 
{ 
    if (length <= 0) yield break ; 

    for (Char c = '!'; c <= '~'; c++) 
    { 
    if (length > 1) 
    { 
     foreach (String restWord in GetWords(length - 1)) 
     yield return c + restWord; 
    } 
    else 
     yield return "" + c; 
    } 
} 
+0

請澄清你的問題。有關的方法使用'yield'關鍵字的更多信息,請參閱MSDN條目(http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx)。 – grovesNL

+0

該方法創建具有特定長度的所有可能的字符串。我想寫一個tsql,使所有可能的字符串具有特定的長度,如c#方法 – AComputer

+0

我仍然不確定你的意思。你的問題是什麼? – grovesNL

回答

1

你一定要明白,你不認爲你正在做的基本上是產生基礎-94數字的序列...你正在生成的字符串的領域得到變化大,速度非常快。例如,使用的字符集(0×21 –的0x7E),有

  • 8836可能(94 )2字符字符串
  • 830584可能的(94 )3-字符串
  • 78074896可能(94 )4字符串
  • 通過你已經打了6個字符的時候,你看94 或689,869,781,056個字符串來生成。

因此,如果您要這樣做,請創建一個SQL Server CLR table-valued function以實時生成它們。

你建立你的字符串的方式很可能是......一點點硬的醇」堆和字符串實習生表。對於初學者來說,我會標記程序集不要通過程序集屬性CompilationRelaxationsAttribute進行字符串實習。

,並使用該使用單個固定大小StringBuilder的非遞歸方法。這裏有一個SQL Server表值函數,它使用這種方法完成你的代碼(我認爲):

using Microsoft.SqlServer.Server; 

class MySqlServerDotNetFunctions 
{ 

    [SqlFunction(TableDefinition="id int not null , value varchar(2000)" , FillRowMethodName="FillRow")] 
    public static IEnumerable<Tuple<long,StringBuilder>> GenerateStrings(int stringLength) 
    { 
    const char lowerBound = '!' ; 
    const char upperBound = '~' ; 
    if (stringLength < 1 || stringLength > 2000) throw new ArgumentOutOfRangeException("stringLength","string length must be in the range 1-2000") ; 

    // initialize the stringbuilder 
    bool   carry = false ; // carry flag 
    StringBuilder sb = new StringBuilder(new string(lowerBound,stringLength)) ; 
    for (long i = 0 ; !carry && ++i > 0 ;) 
    { 
     // return the current iteration 
     yield return new Tuple<long,StringBuilder>(i,sb) ; 

     // increment our string 
     int p  = sb.Length-1 ; // we work right-to-left 
     do 
     { 
     carry = ++sb[p] > upperBound ; 
     if (carry) 
     { 
      sb[p] = lowerBound ; 
     } 
     } while (carry && --p >= 0) ; 

    } 
    } 

    public static void FillRow(object o , out long id , out string value) 
    { 
    Tuple<long,StringBuilder> item = (Tuple<long,StringBuilder>) o ; 

    id = item.Item1   ; 
    value = item.Item2.ToString() ; 
    return ; 
    } 

}