Как передать массив с плавающей точкой в ​​хранимую процедуру SQL Server? - PullRequest
2 голосов
/ 10 мая 2011

Мне нужно записать массив из 36 операций с плавающей запятой в базу данных SQL Server 2005. Есть ли ответ по передовому опыту, объясняющий, как это сделать?

Я не могу записать это как строку, потому что нам может потребоваться запросить отдельные значения для миллионов строк, и мне не нужно разбирать каждую строку, чтобы прочитать ее значение.

Я также хотел бы избежать передачи 36 параметров хранимой процедуры.

Итак, что рекомендует традиционное мнение StackOverflow?

Ответы [ 5 ]

2 голосов
/ 10 мая 2011

В 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, поэтому мой синтаксис может быть немного отключен, но в основном он должен быть правильным.

1 голос
/ 10 мая 2011

Если бы это было 360 или 3600, я бы сказал, XML или строка, но 36, вероятно, все еще достаточно мал, чтобы рассмотреть параметры.

Основная причина, по которой я это говорю, заключается в том, что когда вы переходите к тексту вместо строго типизированных параметров, вы должны постоянно заботиться о форматировании. Кроме того, форматирование чисел может быть сложным: запятые используются для разделителей тысяч в одних странах и десятичных разделителей в других. Если ваш код клиентского доступа работает с региональными настройками, отличными от ожидаемых хранимой процедурой, это может привести к нарушению работы вашего приложения.

1 голос
/ 10 мая 2011

В 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 голос
/ 10 мая 2011

Я бы рекомендовал передавать значения с плавающей точкой в ​​качестве параметра XML, но хранить их в базе данных в 36 отдельных столбцах.(Здесь я предполагаю, что значения с плавающей точкой отличаются друг от друга, и вы захотите вытащить их по отдельности.)

Как вы сказали, вам не нужно разбиратькаждая строка, чтобы прочитать его значение, поэтому вам нужно 36 столбцов.(Это тоже хорошая практика).Но вы можете передать значения с плавающей точкой в ​​виде фрагмента XML, который можно разбирать различными способами, чтобы получить отдельные значения.

0 голосов
/ 09 марта 2016

Используйте это, чтобы передать массив, используя "создать таблицу типов".простой пример для пользователя

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...