【问题标题】:VarBinary(max) to list of integersVarBinary(max) 到整数列表
【发布时间】:2022-01-03 18:54:12
【问题描述】:

对于我的应用程序,我将一些值转储到 varbinary(max) 列中。 现在我正在尝试再次从那里获取数据,并希望从 sql 中获取包含所有值的列表。

在我的 C# 应用程序中,我执行以下任务:

Data = ints.SelectMany(BitConverter.GetBytes).ToArray();

然后将此数据插入到数据库中。

我正在寻找的是一个关于如何检索数据的 SQL 脚本,不仅仅是作为一个 blob,而是作为所有值的列表。 所以是这样的:

SELECT * FROM RawData CROSS APPLY CastToInt(SplitBinary(RawData.Data, 4)) WHERE RawDataId = 1;

有人知道实现这种功能的方法吗?

作为背景信息,我正在尝试在 Grafana 中创建 RawData 图表。

【问题讨论】:

    标签: sql-server graph casting grafana varbinarymax


    【解决方案1】:

    拆分 32 位 int 值的一种方法是使用二进制字符串拆分函数。下面的 TVF 示例使用实用程序计数表来简化任务。

    Tally 表 DDL:

    DROP TABLE IF EXISTS dbo.Tally;
    CREATE TABLE dbo.Tally(Number int NOT NULL);
    --load 1 million numbers
    WITH 
         t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
        ,t1k AS (SELECT 0 AS n FROM t10 AS t10a CROSS JOIN t10 AS t10b CROSS JOIN t10 AS t10c)
        ,t1m AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS Number FROM t1k AS t1ka CROSS JOIN t1k AS t1kb)
    INSERT INTO dbo.Tally WITH(TABLOCKX) (Number) 
    SELECT Number
    FROM t1m;
    --create primary key on number
    ALTER TABLE dbo.Tally
        ADD CONSTRAINT PK_Tally PRIMARY KEY (Number)
        WITH(FILLFACTOR=100, MAXDOP = 1);
    GO
    

    二进制 int 拆分 TVF:

    CREATE OR ALTER FUNCTION dbo.BINARY_INT_STRING_SPLIT(@ints varbinary(MAX))
    RETURNS TABLE
    AS
    RETURN(
        --reverse serialized bytes for little-endian order
        SELECT CAST(SUBSTRING(@ints,Tally.Number*4,1) + SUBSTRING(@ints,Tally.Number*4-1,1) + SUBSTRING(@ints,Tally.Number*4-2,1) + SUBSTRING(@ints,Tally.Number*4-3,1) AS int) AS int
        FROM dbo.Tally
        WHERE Tally.Number <= DATALENGTH(@ints)/4
    );
    GO
    

    示例用法:

    CREATE TABLE dbo.RawData(RawDataId int, Data varbinary(MAX));
    INSERT INTO dbo.RawData(RawDataId, Data) VALUES(1, 0x01000000);
    INSERT INTO dbo.RawData(RawDataId, Data) VALUES(2, 0x02000000);
    INSERT INTO dbo.RawData(RawDataId, Data) VALUES(3, 0xffffffff);
    GO
    
    SELECT RawDataId, ints.int
    FROM dbo.RawData
    CROSS APPLY dbo.BINARY_INT_STRING_SPLIT(RawData.Data) AS ints;
    GO
    

    【讨论】:

    • 这看起来很有希望!这是否也可以重写以使用实数?
    • @Foitn,T-SQL 不允许从 varbinary 转换为 real/float。即使是这样,不同的 .NET 单一数据类型和 SQL Server 浮点数据类型结构和字节序也可能会带来额外的复杂性。恕我直言,SQLCLR 函数将更适合实际转换。
    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 2013-01-10
    • 1970-01-01
    相关资源
    最近更新 更多