1
これらのC#アレイパックデリミタをエスケープし、ヌル、ヌル配列、空の配列を保持するアンパックユーティリティメソッドをt-sqlの熟練者はコンパニオンテーブル値関数を作成できますか往復のエンコーディングを通じて?C#およびT-SQL文字列[]パック/アンパックユーティリティ関数
さまざまな文字列配列を文字列にパックすることによって、そのような(小さい)配列をパラメータとしてSQLに渡すことができます。これはいくつかのシナリオで便利です。
static class ArrayUtil
{
public static string Pack(string[] original)
{
return Pack(original, '|', '0', '~');
}
public static string[] Unpack(string original)
{
return Unpack(original, '|', '0', '~');
}
public static string Pack(string[] original, char delimiter, char zed, char escape)
{
if (delimiter == escape ||
zed == escape ||
delimiter == zed) throw new ArgumentException("special characters must be distinct");
// Null array returns a null string
if (original == null) return null;
// Empty array returns an empty string
if (original.Length == 0) return string.Empty;
// Arrays with a single empty element are represented as just the escape character
// to differentiate from an empty array
if (original.Length == 1 && original[0] == string.Empty) return escape.ToString();
// Otherwise
StringBuilder sb = new StringBuilder();
for (int i = 0, ol = original.Length; i < ol; i++)
{
string s = original[i];
if (s == null)
{
sb.Append(zed); // zed == null
}
else
{
for (int j = 0, sl = s.Length; j < sl; j++)
{
char c = s[j];
// escape literal delimiters, escapes, and leading zeds
if (c == delimiter ||
c == escape ||
(c == zed && j == 0)) sb.Append(escape);
sb.Append(c);
}
}
if (i != ol - 1) sb.Append(delimiter); // no trailing delimiter
}
return sb.ToString();
}
public static string[] Unpack(string original, char delimiter, char zed, char escape)
{
if (delimiter == escape ||
zed == escape ||
delimiter == zed) throw new ArgumentException("special characters must be distinct");
// Null string returns a null array
if (original == null) return null;
// Empty string returns an empty array
if (original == string.Empty) return new string[] { };
// A single escape character represents an array with a single empty element
// to differentiate from an empty array
if (original == escape.ToString()) return new string[] { string.Empty };
// Otherwise
StringBuilder sb = new StringBuilder(); // A place to store the current element
StringReader sr = new StringReader(original); // A stream of the original string
List<string> unpacked = new List<string>(); // The finished elements
int next;
while ((next = sr.Read()) >= 0)
{
char c = (char)next;
if (c == zed && sb.Length == 0)
{
unpacked.Add(null);
if ((next = sr.Peek()) >= 0 && (char)next != delimiter)
throw new ArgumentException("An element's leading zed character must be escaped or must alone be the element", "original");
sb = null;
}
else if (c == delimiter)
{
if (sb != null) unpacked.Add(sb.ToString());
sb = new StringBuilder();
}
else if (c == escape)
{
if ((next = sr.Read()) >= 0)
{
sb.Append((char)next);
}
else
throw new ArgumentException("Escapee expected", "original");
}
else
{
sb.Append(c);
}
}
// A final zed character will make sb = null, but otherwise we have an additional element
if (sb != null) unpacked.Add(sb.ToString());
return unpacked.ToArray();
}
}
例Pack(original, '|', '0', '~')
とパッキン、基本ケース:
["hello", "world"] -> "hello|world"
いくつかの特殊なケース(PEXによって発見される)
null -> null
[null] -> "0"
[null, null] -> "0|0"
[] -> ""
[""] -> "~"
["", ""] -> "|"
["|", "|"] -> "~||~|"
これは少しばかりです。 [PackStrings.sql](https://gist.github.com/JasonKleban/102788bd73f7f4f8b10807f567ab2ebd)、[UnpackStrings.sql](https://gist.github.com/JasonKleban/e8ea898c4e4fb71ca711937a2241a505)、改良されたC#[ PackUtil.cs](https://gist.github.com/JasonKleban/ab74920c41e805f5696117d7aa0a03d8) –