2011-05-10 68 views
2

我需要將一個由36個浮點數組成的數組寫入SQL Server 2005數據庫。是否有最佳實踐答案解釋如何做到這一點?如何將一個浮點數組傳遞給SQL Server存儲過程?

我不能把它寫成字符串,因爲我們可能需要查詢數百萬行的單個值,而且我不想爲了讀取它的值而去解構每一行。

我也想避免將36個參數傳遞給存儲過程。

那麼,StackOverflow的傳統智慧推薦什麼?

+1

升級到SQL Server 2008,並使用[表值參數(http://msdn.microsoft.com/en-us/library/bb675163.aspx) – 2011-05-10 20:28:56

回答

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

我建議將浮點數作爲XML參數傳遞,但將其存儲在數據庫中的36個單獨列中。 (我假設這裏的花車彼此的意義是不同的,並且你會想單獨將它們拉出來。)

正如你所說的,你不需要去構造每一行閱讀它的價值,所以你需要36列。 (這也是很好的做法)。但是您可以將浮點數作爲XML片段傳遞,您可以通過各種方式分離浮點數以獲取各個值。

+1

如何爲36列,其都是一樣的好習慣嗎?聽起來像正常化的候選人。我會去索引和價值列單獨的表。 – 2011-05-10 19:00:17

+0

在SQL Server中,XML處理可能非常耗費CPU資源。除非你絕對必須使用它,否則通常最好避免。 – 2011-05-10 19:04:22

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 
+1

我剛剛發佈相同的答案:) – 2011-05-10 18:54:58

1

如果是360或3600,我會說XML或一個字符串,但36可能仍然足夠小,以考慮參數。

我這樣說的主要原因是因爲當你轉到文本而不是強類型參數時,你必須考慮一致的格式。數字格式化可以用一些國家的數千個分隔符和其他數字中的小數點分隔符使用逗號來挑剔。如果您的客戶端訪問代碼運行的區域設置不同於存儲過程預期的區域設置,則可能會發現它破壞了您的應用程序。

0

使用它可以使用「創建類型表」傳遞數組。簡單的例子爲用戶

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 
相關問題