我需要将一个包含36个浮点数组的数组写入SQL Server 2005数据库。是否有最佳实践答案解释如何执行此操作?
我不能把它写成字符串,因为我们可能需要查询数百万行的单个值,而且我不想要解构每一行来读取它的值。
我还想避免将36个参数传递给存储过程。
那么,StackOverflow的传统智慧推荐什么呢?
答案 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