如何解决在SQL Server语句中将StringBuilder用作SQL CLR UDF
sql Server缺少一个StringBuilder
UDF,如何克服此限制?
这是我为克服问题而构建的:
您可以在sql语句中使用它,请注意,SET
方法的每次调用都需要Append
变量。
DECLARE @stringBuilder StringBuilder = StringBuilder::Parse('');
SET @stringBuilder = @stringBuilder.AppendLine('Hello,');
SET @stringBuilder = @stringBuilder.AppendLine('World');
PRINT @stringBuilder.ToString();
-- (This is the same functionality as above)
-- PRINT @stringBuilder.AppendLine('Hello,').AppendLine('World').ToString();
你好, 世界
还有其他一些方法,例如Append
,Replace
,Insert
,Remove
和Clear
。
#region Imported Types
using Microsoft.sqlServer.Server;
using System;
using System.Data.sqlTypes;
using System.IO;
#endregion
namespace sqlServer.Types
{
[Serializable()]
[sqlUserDefinedType(Format.UserDefined,IsByteOrdered = false,IsFixedLength = false,MaxByteSize = -1)]
public struct StringBuilder : INullable,IBinarySerialize
{
#region Fields
private System.Text.StringBuilder _stringBuilder;
#endregion
#region Properties
public bool IsNull
{
get;
internal set;
}
private System.Text.StringBuilder _StringBuilder
{
get
{
if (_stringBuilder == null)
{
_stringBuilder = new System.Text.StringBuilder();
}
return _stringBuilder;
}
set
{
_stringBuilder = value;
}
}
public int Length
{
get
{
return _StringBuilder.Length;
}
}
#endregion
#region Helper Methods
public static StringBuilder Null
{
get
{
return (new StringBuilder() { IsNull = true });
}
}
[return: sqlFacet(MaxSize = -1)]
public override string ToString()
{
return _StringBuilder.ToString();
}
public StringBuilder Append(sqlString value)
{
if (!value.IsNull)
{
_StringBuilder.Append(value.Value);
}
return this;
}
public StringBuilder AppendLine(sqlString value)
{
if (!value.IsNull)
{
_StringBuilder.AppendLine(value.Value);
}
return this;
}
public StringBuilder Insert(sqlInt32 index,sqlString value)
{
if (!index.IsNull)
{
if (!value.IsNull)
{
_StringBuilder.Insert(index.Value,value.Value);
}
}
return this;
}
public StringBuilder Remove(sqlInt32 index,sqlInt32 length)
{
if (!index.IsNull)
{
if (!length.IsNull)
{
_StringBuilder.Remove(index.Value,length.Value);
}
}
return this;
}
public StringBuilder Replace(sqlString oldValue,sqlString newValue)
{
if (!oldValue.IsNull)
{
if (!newValue.IsNull)
{
_StringBuilder.Replace(oldValue.Value,newValue.Value);
}
}
return this;
}
public StringBuilder Clear()
{
_StringBuilder.Clear();
return this;
}
public static StringBuilder Parse(sqlString stringToParse)
{
if (stringToParse.IsNull)
{
return Null;
}
return (new StringBuilder() { _StringBuilder = new System.Text.StringBuilder(stringToParse.Value) });
}
#endregion
#region Serialization Methods
public void Read(BinaryReader binaryReader)
{
IsNull = binaryReader.ReadBoolean();
if (IsNull)
{
return;
}
else
{
_StringBuilder = new System.Text.StringBuilder(binaryReader.ReadString());
}
}
public void Write(BinaryWriter binaryWriter)
{
binaryWriter.Write(IsNull);
binaryWriter.Write(_StringBuilder.ToString());
}
#endregion
}
}
CREATE PROCEDURE [System].[GenerateUnitConverter]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @stringBuilder StringBuilder = StringBuilder::Parse('');
DECLARE @unitId int;
DECLARE @unitName varchar(255);
DECLARE @unitSymbol varchar(32);
DECLARE @convertFrom varchar(255);
DECLARE @convertTo varchar(255);
DECLARE @baseUnitId int;
DECLARE @formulaTypeId int;
DECLARE @unitClassId int;
DECLARE @unitClassName varchar(255);
DECLARE @unitsPathLocator hierarchyid;
SELECT @unitsPathLocator = [path_locator]
FROM [System].[Resources]
WHERE [path_locator].GetLevel() = 1 AND is_directory = 1 AND [name] = 'Units';
SET @stringBuilder = @stringBuilder.AppendLine('using System;');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine('namespace EnerWorx.Units');
SET @stringBuilder = @stringBuilder.AppendLine('{');
SET @stringBuilder = @stringBuilder.AppendLine(' public static class Converter');
SET @stringBuilder = @stringBuilder.AppendLine(' {');
SET @stringBuilder = @stringBuilder.AppendLine(' public static double Convert(double value,int fromunitId,int toUnitId)');
SET @stringBuilder = @stringBuilder.AppendLine(' {');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine(' var baseValue = 0.0;');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine(' if(fromunitId == toUnitId) return value;');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine(' switch(fromunitId)');
SET @stringBuilder = @stringBuilder.AppendLine(' {');
DECLARE unit_cursor CURSOR FOR
SELECT Units.Units.Id AS UnitId,Units.Units.Name AS UnitName,Units.Units.Symbol AS UnitSymbol,Units.Units.ConvertFrom,Units.Units.ConvertTo,Units.Units.BaseUnitId,Units.Units.FormulaTypeId,Units.Units.UnitClassId,Units.UnitClasses.Name AS UnitClassName
FROM Units.Units
LEFT OUTER JOIN Units.UnitClasses ON Units.Units.UnitClassId = Units.UnitClasses.Id
ORDER BY UnitId
OPEN unit_cursor
FETCH NEXT FROM unit_cursor
INTO @unitId,@unitName,@unitSymbol,@convertFrom,@convertTo,@baseUnitId,@formulaTypeId,@unitClassId,@unitClassName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' case ' + CAST(@unitId AS varchar(128)) + ': // ' + @unitClassName + ': ' + @unitName + ' (' + @unitSymbol + ')');
IF (@baseUnitId IS NULL)
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' baseValue = value;');
END
ELSE
BEGIN
IF(@formulaTypeId = 0) -- Factor
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' baseValue = value * ' + @convertFrom + ';');
END
IF(@formulaTypeId = 1) -- Formula
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' baseValue = ' + StringBuilder::Parse(@convertFrom).Replace('X','value').ToString() +';');
END
IF(@formulaTypeId = 2) -- Add
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' baseValue = value + ' + @convertFrom + ';');
END
END
SET @stringBuilder = @stringBuilder.AppendLine(' break;');
FETCH NEXT FROM unit_cursor
INTO @unitId,@unitClassName
END
CLOSE unit_cursor;
SET @stringBuilder = @stringBuilder.AppendLine(' default: throw new NotImplementedException("Unsupported convert from unit id");');
SET @stringBuilder = @stringBuilder.AppendLine(' }');
SET @stringBuilder = @stringBuilder.AppendLine('');
SET @stringBuilder = @stringBuilder.AppendLine(' switch(toUnitId)');
SET @stringBuilder = @stringBuilder.AppendLine(' {');
OPEN unit_cursor
FETCH NEXT FROM unit_cursor
INTO @unitId,@unitClassName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' case ' + CAST(@unitId AS varchar(128)) + ': // ' + @unitClassName + ': ' + @unitName + ' (' + @unitSymbol + ');');
IF (@baseUnitId IS NULL)
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' return baseValue;');
END
ELSE
BEGIN
IF(@formulaTypeId = 0) -- Factor
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' return baseValue / ' + @convertFrom + ';');
END
IF(@formulaTypeId = 1) -- Formula
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' return ' + StringBuilder::Parse(@convertTo).Replace('X','baseValue').ToString() + ';');
END
IF(@formulaTypeId = 2) -- Add
BEGIN
SET @stringBuilder = @stringBuilder.AppendLine(' return baseValue - ' + @convertFrom + ';');
END
END
FETCH NEXT FROM unit_cursor
INTO @unitId,@unitClassName
END
CLOSE unit_cursor;
DEALLOCATE unit_cursor;
SET @stringBuilder = @stringBuilder.AppendLine(' default: throw new NotImplementedException("Unsupported convert to unit id");');
SET @stringBuilder = @stringBuilder.AppendLine(' }');
SET @stringBuilder = @stringBuilder.AppendLine(' }');
SET @stringBuilder = @stringBuilder.AppendLine(' }');
SET @stringBuilder = @stringBuilder.AppendLine('}');
DECLARE @fileStream varbinary(max) = CAST(CAST(@stringBuilder.ToString() AS varchar(max)) AS varbinary(max));
EXEC [System].[CreateResourceFile] @unitsPathLocator,'Units.cs',@fileStream,1;
DECLARE @unitsPathLocatorNative varbinary(max) = CAST(@unitsPathLocator as varbinary(max));
EXECUTE [dbo].[CompileAssembly] @unitsPathLocatorNative,'EnerWorx.Units.dll','System.dll';
END
using System;
namespace EnerWorx.Units
{
public static class Converter
{
public static double Convert(double value,int toUnitId)
{
var baseValue = 0.0;
if(fromunitId == toUnitId) return value;
switch(fromunitId)
{
case 1000: // Absorbed Dose: Gray (Gy)
baseValue = value;
break;
case 1001: // Absorbed Dose: yottagray (YGy)
baseValue = value * 1E24;
break;
case 1002: // Absorbed Dose: zettagray (ZGy)
baseValue = value * 1E21;
break;
case 1003: // Absorbed Dose: exagray (EGy)
baseValue = value * 1E18;
break;
case 1004: // Absorbed Dose: petagray (PGy)
baseValue = value * 1E15;
break;
case 1005: // Absorbed Dose: teragray (TGy)
baseValue = value * 1E12;
break;
case 1006: // Absorbed Dose: gigagray (GGy)
baseValue = value * 1E9;
break;
case 1007: // Absorbed Dose: megagray (MGy)
baseValue = value * 1E6;
break;
case 1008: // Absorbed Dose: kilogray (kGy)
baseValue = value * 1E3;
break;
case 1009: // Absorbed Dose: hectogray (hGy)
baseValue = value * 100.0;
break;
case 1010: // Absorbed Dose: dekagray (daGy)
baseValue = value * 10.0;
break;
case 1011: // Absorbed Dose: decigray (dGy)
baseValue = value * 0.1;
break;
case 1012: // Absorbed Dose: centigray (cGy)
baseValue = value * 0.01;
break;
case 1013: // Absorbed Dose: milligray (mGy)
baseValue = value * 0.001;
break;
case 1014: // Absorbed Dose: microgray (µGy)
baseValue = value * 1E-6;
break;
case 1015: // Absorbed Dose: nanogray (nGy)
baseValue = value * 1E-9;
break;
case 1016: // Absorbed Dose: picogray (pGy)
baseValue = value * 1E-12;
break;
case 1017: // Absorbed Dose: femtogray (fGy)
baseValue = value * 1E-15;
break;
case 1018: // Absorbed Dose: attogray (aGy)
baseValue = value * 1E-18;
break;
case 1019: // Absorbed Dose: zeptogray (zGy)
baseValue = value * 1E-21;
break;
case 1020: // Absorbed Dose: yoctogray (yGy)
baseValue = value * 1E-24;
break;
case 1021: // Absorbed Dose: rad (rd)
baseValue = value * 0.01;
break;
case 1022: // Absorbed Dose: joule per kilogram (J/kg)
baseValue = value * 1.0;
break;
case 1023: // Absorbed Dose: joule per gram (J/g)
baseValue = value * 1000.0;
break;
case 1024: // Absorbed Dose: joule per centigram (J/cm)
baseValue = value * 100000.0;
break;
case 1025: // Absorbed Dose: joule per milligram (J/mg)
baseValue = value * 1000000.0;
break;
case 2000: // acceleration: meters per second squared (m/s²)
baseValue = value;
break;
case 2001: // acceleration: yottametres per second squared (Ym/s²)
baseValue = value * 1E24;
break;
case 2002: // acceleration: zettametres per second squared (Zm/s²)
baseValue = value * 1E21;
break;
case 2003: // acceleration: exametres per second squared (Em/s²)
baseValue = value * 1E18;
break;
case 2004: // acceleration: petametres per second squared (Pm/s²)
baseValue = value * 1E15;
break;
case 2005: // acceleration: terametres per second squared (Tm/s²)
baseValue = value * 1E12;
break;
case 2006: // acceleration: gigametres per second squared (Gm/s²)
baseValue = value * 1E9;
break;
case 2007: // acceleration: megametres per second squared (Mm/s²)
baseValue = value * 1E6;
break;
case 2008: // acceleration: kilometres per second squared (km/s²)
baseValue = value * 1E3;
break;
case 2009: // acceleration: hectmetres per second squared (hm/s²)
baseValue = value * 1E2;
break;
case 2010: // acceleration: dekametres per second squared (dam/s²)
baseValue = value * 10.0;
break;
case 2011: // acceleration: decimetres per second squared (dm/s²)
baseValue = value * 0.1;
break;
case 2012: // acceleration: centimetres per second squared (cm/s²)
baseValue = value * 0.01;
break;
case 2013: // acceleration: millimetres per second squared (mm/s²)
baseValue = value * 0.001;
break;
case 2014: // acceleration: micrometres per second squared (µm/s²)
baseValue = value * 1E-6;
break;
case 2015: // acceleration: nanometres per second squared (nm/s²)
baseValue = value * 1E-9;
break;
case 2016: // acceleration: picometres per second squared (pm/s²)
baseValue = value * 1E-12;
break;
case 2017: // acceleration: femtometres per second squared (fm/s²)
baseValue = value * 1E-15;
break;
case 2018: // acceleration: attometres per second squared (am/s²)
baseValue = value * 1E-18;
break;
case 2019: // acceleration: zeptometres per second squared (zm/s²)
baseValue = value * 1E-21;
break;
case 2020: // acceleration: yoctometres per second squared (ym/s²)
baseValue = value * 1E-24;
break;
case 2021: // acceleration: galileo (gal)
baseValue = value * 0.01;
break;
case 2022: // acceleration: gravity (g)
baseValue = value * 9.80665;
break;
case 2023: // acceleration: inches per second squared (in/s²)
baseValue = value * 0.0254;
break;
case 2024: // acceleration: feet per second squared (ft/s²)
baseValue = value * 0.3048;
break;
case 2025: // acceleration: yards per second squared (yd/s²)
baseValue = value * 0.9144;
break;
case 2026: // acceleration: miles per second squared (mi/s²)
baseValue = value * 1609.344;
break;
case 3000: // Angle: degrees (°)
baseValue = value;
break;
case 3001: // Angle: radians (rad)
baseValue = value * 57.29577951;
break;
case 3002: // Angle: gradians (grad)
baseValue = value * 0.9;
break;
case 3003: // Angle: revolution (rev)
baseValue = value * 360.0;
break;
case 3004: // Angle: minute (min)
baseValue = value * 0.0166666666666667;
break;
case 3005: // Angle: second (sec)
baseValue = value * 0.000277777777777778;
break;
case 3006: // Angle: mil (mil)
baseValue = value * 0.05625;
break;
default: throw new NotImplementedException("Unsupported convert from unit id");
}
switch(toUnitId)
{
case 1000: // Absorbed Dose: Gray (Gy);
return baseValue;
case 1001: // Absorbed Dose: yottagray (YGy);
return baseValue / 1E24;
case 1002: // Absorbed Dose: zettagray (ZGy);
return baseValue / 1E21;
case 1003: // Absorbed Dose: exagray (EGy);
return baseValue / 1E18;
case 1004: // Absorbed Dose: petagray (PGy);
return baseValue / 1E15;
case 1005: // Absorbed Dose: teragray (TGy);
return baseValue / 1E12;
case 1006: // Absorbed Dose: gigagray (GGy);
return baseValue / 1E9;
case 1007: // Absorbed Dose: megagray (MGy);
return baseValue / 1E6;
case 1008: // Absorbed Dose: kilogray (kGy);
return baseValue / 1E3;
case 1009: // Absorbed Dose: hectogray (hGy);
return baseValue / 100.0;
case 1010: // Absorbed Dose: dekagray (daGy);
return baseValue / 10.0;
case 1011: // Absorbed Dose: decigray (dGy);
return baseValue / 0.1;
case 1012: // Absorbed Dose: centigray (cGy);
return baseValue / 0.01;
case 1013: // Absorbed Dose: milligray (mGy);
return baseValue / 0.001;
case 1014: // Absorbed Dose: microgray (µGy);
return baseValue / 1E-6;
case 1015: // Absorbed Dose: nanogray (nGy);
return baseValue / 1E-9;
case 1016: // Absorbed Dose: picogray (pGy);
return baseValue / 1E-12;
case 1017: // Absorbed Dose: femtogray (fGy);
return baseValue / 1E-15;
case 1018: // Absorbed Dose: attogray (aGy);
return baseValue / 1E-18;
case 1019: // Absorbed Dose: zeptogray (zGy);
return baseValue / 1E-21;
case 1020: // Absorbed Dose: yoctogray (yGy);
return baseValue / 1E-24;
case 1021: // Absorbed Dose: rad (rd);
return baseValue / 0.01;
case 1022: // Absorbed Dose: joule per kilogram (J/kg);
return baseValue / 1.0;
case 1023: // Absorbed Dose: joule per gram (J/g);
return baseValue / 1000.0;
case 1024: // Absorbed Dose: joule per centigram (J/cm);
return baseValue / 100000.0;
case 1025: // Absorbed Dose: joule per milligram (J/mg);
return baseValue / 1000000.0;
case 2000: // acceleration: meters per second squared (m/s²);
return baseValue;
case 2001: // acceleration: yottametres per second squared (Ym/s²);
return baseValue / 1E24;
case 2002: // acceleration: zettametres per second squared (Zm/s²);
return baseValue / 1E21;
case 2003: // acceleration: exametres per second squared (Em/s²);
return baseValue / 1E18;
case 2004: // acceleration: petametres per second squared (Pm/s²);
return baseValue / 1E15;
case 2005: // acceleration: terametres per second squared (Tm/s²);
return baseValue / 1E12;
case 2006: // acceleration: gigametres per second squared (Gm/s²);
return baseValue / 1E9;
case 2007: // acceleration: megametres per second squared (Mm/s²);
return baseValue / 1E6;
case 2008: // acceleration: kilometres per second squared (km/s²);
return baseValue / 1E3;
case 2009: // acceleration: hectmetres per second squared (hm/s²);
return baseValue / 1E2;
case 2010: // acceleration: dekametres per second squared (dam/s²);
return baseValue / 10.0;
case 2011: // acceleration: decimetres per second squared (dm/s²);
return baseValue / 0.1;
case 2012: // acceleration: centimetres per second squared (cm/s²);
return baseValue / 0.01;
case 2013: // acceleration: millimetres per second squared (mm/s²);
return baseValue / 0.001;
case 2014: // acceleration: micrometres per second squared (µm/s²);
return baseValue / 1E-6;
case 2015: // acceleration: nanometres per second squared (nm/s²);
return baseValue / 1E-9;
case 2016: // acceleration: picometres per second squared (pm/s²);
return baseValue / 1E-12;
case 2017: // acceleration: femtometres per second squared (fm/s²);
return baseValue / 1E-15;
case 2018: // acceleration: attometres per second squared (am/s²);
return baseValue / 1E-18;
case 2019: // acceleration: zeptometres per second squared (zm/s²);
return baseValue / 1E-21;
case 2020: // acceleration: yoctometres per second squared (ym/s²);
return baseValue / 1E-24;
case 2021: // acceleration: galileo (gal);
return baseValue / 0.01;
case 2022: // acceleration: gravity (g);
return baseValue / 9.80665;
case 2023: // acceleration: inches per second squared (in/s²);
return baseValue / 0.0254;
case 2024: // acceleration: feet per second squared (ft/s²);
return baseValue / 0.3048;
case 2025: // acceleration: yards per second squared (yd/s²);
return baseValue / 0.9144;
case 2026: // acceleration: miles per second squared (mi/s²);
return baseValue / 1609.344;
default: throw new NotImplementedException("Unsupported convert to unit id");
}
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。