【问题标题】:How to pass an array of floats to SQL Server stored procedure?如何将浮点数组传递给 SQL Server 存储过程?
【发布时间】:2011-05-10 18:49:29
【问题描述】:

我需要将一个包含 36 个浮点数的数组写入 SQL Server 2005 数据库。是否有解释如何做到这一点的最佳实践答案?

我不能把它写成一个字符串,因为我们可能需要查询数百万行的单个值,而且我不想解构每一行来读取它的值。

我还想避免将 36 个参数传递给存储过程。

那么,StackOverflow 的传统智慧有什么建议?

【问题讨论】:

标签: sql-server sql-server-2005 stored-procedures


【解决方案1】:

在 Sql Server 2008 中,出于这个原因,存在表值参数。但是,在 2005 年,您只能选择 (1) 字符串连接/拆分或 (2) xml。

我会先传递 XML,然后插入到表变量中。这是一个例子:

declare @floatsXml nvarchar(max);
set @floatsXml = '<nums><num val="2.123" /><num val="2.123" /></nums>';

declare @floats table (value float);

insert into @floats
select tbl.c.value('@val', 'float')
from @floatsXml.nodes('/nums/num') as tbl(c);

select * 
from @floats;

我没有安装当前的 sql server,所以我的语法可能略有偏差,但应该是正确的。

【讨论】:

    【解决方案2】:

    在 SQL Server 2008 中,您可以使用表值参数。由于这是 SQL 2005,因此我使用逗号分隔列表,然后使用拆分函数转换为适当的数据类型并返回一个表。

    这是我使用的拆分功能:

    IF OBJECT_ID('dbo.Nums') IS NOT NULL 
      DROP TABLE dbo.Nums ;
    GO
    
    CREATE TABLE [dbo].[Nums]
      (
       [n] int NOT NULL,
       PRIMARY KEY CLUSTERED ([n] ASC)
        WITH (PAD_INDEX = OFF, FILLFACTOR = 100, IGNORE_DUP_KEY = OFF,
              STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON,
              ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
      )
    ON
      [PRIMARY] ;
    GO
    
    DECLARE @max AS INT,
      @rc AS INT ;
    SET @max = 1000000 ;
    SET @rc = 1 ;
    
    INSERT  INTO dbo.Nums (n)
    VALUES  (1) ;
    WHILE @rc * 2 <= @max
      BEGIN
        INSERT  INTO dbo.Nums (n)
                SELECT  n + @rc
                FROM    dbo.Nums ;
        SET @rc = @rc * 2 ;
      END
    
    INSERT  INTO dbo.Nums (n)
            SELECT  n + @rc
            FROM    dbo.Nums
            WHERE   n + @rc <= @max ;
    GO
    
    CREATE FUNCTION [dbo].[fn_split]
    (@arr nvarchar(4000), @sep nchar(1))
    RETURNS table
    AS
    RETURN
      SELECT    (n - 1) - LEN(REPLACE(LEFT(@arr, n-1), @sep, N'')) + 1 AS pos,
                    SUBSTRING(@arr, n, CHARINDEX(@sep, @arr + @sep, n) - n) AS element
      FROM      dbo.Nums
      WHERE     n <= LEN(@arr) + 1
                    AND SUBSTRING(@sep + @arr, n, 1) = @sep;
    GO
    

    【讨论】:

    • 我正要发布相同的答案:)
    【解决方案3】:

    如果是 360 或 3600,我会说 XML 或字符串,但 36 可能仍然小到可以考虑参数。

    我这么说的主要原因是,当您使用文本而不是强类型参数时,您必须担心格式的一致性。数字格式可能很挑剔,在某些国家/地区使用逗号作为千位分隔符,在其他国家/地区使用小数分隔符。如果您的客户端访问代码以不同于存储过程预期的区域设置运行,您可能会发现它破坏了您的应用程序。

    【讨论】:

      【解决方案4】:

      我建议将浮点数作为 XML 参数传递,但将其存储在数据库中的 36 个单独列中。 (我在这里假设浮动在含义上彼此不同,并且您需要将它们单独拉出。)

      正如您所说,您不希望必须解构每一行来读取其值,因此您需要 36 列。 (这也是一个很好的做法)。但是您可以将浮点数作为 XML 片段传递,您可以通过多种方式将其拆开,以便取出各个值。

      【讨论】:

      • 36 列都一样是一个好习惯吗?听起来像是标准化的候选人。我会选择一个带有索引和值列的单独表。
      • XML 处理在 SQL Server 中可能会占用大量 CPU。除非您绝对必须使用它,否则通常最好避免使用它。
      【解决方案5】:

      使用它通过“创建类型表”传递数组。用户的简单示例

      CREATE TYPE unit_list AS TABLE (
          ItemUnitId int,
          Amount float,
          IsPrimaryUnit bit
      );
      
      GO
       CREATE TYPE specification_list AS TABLE (
           ItemSpecificationMasterId int,
          ItemSpecificationMasterValue varchar(255)
      );
      
      GO
       declare @units unit_list;
       insert into @units (ItemUnitId, Amount, IsPrimaryUnit) 
        values(12,10.50, false), 120,100.50, false), (1200,500.50, true);
      
       declare @spec specification_list;
        insert into @spec (ItemSpecificationMasterId,temSpecificationMasterValue) 
         values (12,'test'), (124,'testing value');
      
       exec sp_add_item "mytests", false, @units, @spec
      
      
      //Procedure definition
      CREATE PROCEDURE sp_add_item
      (   
          @Name nvarchar(50),
          @IsProduct bit=false,
          @UnitsArray unit_list READONLY,
          @SpecificationsArray specification_list READONLY
      )
      AS
      
      
      BEGIN
          SET NOCOUNT OFF     
      
          print @Name;
          print @IsProduct;       
          select * from @UnitsArray;
          select * from @SpecificationsArray;
      END
      

      【讨论】:

        猜你喜欢
        • 2014-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-21
        • 2021-04-28
        • 1970-01-01
        相关资源
        最近更新 更多