如何将一个浮点数组传递给SQL Server存储过程?

时间:2011-05-10 18:49:29

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

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

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

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

那么,StackOverflow的传统智慧推荐什么呢?

5 个答案:

答案 0 :(得分:2)

在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,所以我的语法可能略有偏差,但它应该是正确的。

答案 1 :(得分:1)

我建议将浮点数作为XML参数传递,但将其存储在36个单独的列中的数据库中。 (我在这里假设花车彼此之间的意义不同,你想要将它们单独拉出来。)

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

答案 2 :(得分:1)

使用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 :(得分:1)

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

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

答案 4 :(得分:0)

使用此选项使用&#34;创建类型表&#34;来传递数组。用户的简单示例

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