微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在SQL Server语句中将StringBuilder用作SQL CLR UDF

如何解决在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();

你好, 世界

还有其他一些方法,例如AppendReplaceInsertRemoveClear

#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 举报,一经查实,本站将立刻删除。