Отправляет email-рассылки с помощью сервиса Sendsay

Вопросы и ответы по MS SQL Server

  Все выпуски  

Вопросы и ответы по MS SQL Server


Информационный Канал Subscribe.Ru


Вопросы и ответы по MS SQL Server

Выпуск No. 15 от 2003-05-30

Вопрос : Существует ли в SQL Server тип переменной array (массив)?

Ответ:
В стандарте ANSI SQL 92 нет массивов, и в SQL Server их тоже нет.
А для чего в SQL могут понадобиться массивы? Вот основные поводы:
1. Передать заполненный массив в хранимую процедуру.
2. Работать с массивами так, как это принято в других языках программирования.
3. Хранить массивы в строках таблицы.

Рассмотрим разрешение всех этих проблем по очереди.

1. Передать заполненный массив в хранимую процедуру.
Проблему передачи списка значений в хранимую процедуру каждый решает как может. Рассмотрим несколько вариантов ее решения. Каждый из этих вариантов имеет свою нишу для применения.

Вариант 1.
В процедуру можно передать одну или несколько переменных типа varchar, содержащие значения, разделенные запятой, или имеющие равную длину для каждого значения. А затем занести эти значения во временную таблицу или использовать их как есть.
1) Перенос во временную таблицу:
use tempdb

GO
if OBJECT_ID('Test1') IS NOT NULL drop procedure Test1
GO
CREATE PROCEDURE Test1 @Param varchar(200)
AS
BEGIN
select *
from sysobjects
where type in (
-- перевод строки в таблицу параметров
-- в MSSQL 2000 удобнее создать пользовательскую функцию
select SUBSTRING(@Param, a.i,
CASE WHEN CHARINDEX(',', @Param, a.i)>0

THEN CHARINDEX(',', @Param, a.i)-(a.i)
ELSE 8000
END) AS Value
from (
-- таблица значений 1,2,3.... (лучше перевести в специальную таблицу)
select count(*) as i
from master..sysobjects a, master..sysobjects b
where a.id<b.id
group by a.id

) a
where (a.i=1 or SUBSTRING(@Param, a.i-1, 1)=',')
and a.i<=LEN(@Param)
)
END
GO
-- вызов процедуры
exec Test1 'S,V,P'
GO

2) Использование строки "как есть":
use tempdb

GO
if OBJECT_ID('Test1') IS NOT NULL drop procedure Test1
GO
CREATE PROCEDURE Test1 @Param varchar(200)
AS
BEGIN
select *
from sysobjects
where CHARINDEX(','+rtrim(type)+',', ','+@Param+',')>0
END
GO
-- вызов процедуры
exec Test1 'S,V,P'
GO


Вариант 2.
Более широко используемым вариантом является передача в хранимую процедуру имени ранее заполненной временной таблицы.
use tempdb

GO
if OBJECT_ID('Test1') IS NOT NULL drop procedure Test1
GO
CREATE PROCEDURE Test1 @Param varchar(200)
AS
BEGIN
SET NOCOUNT ON
create table #Temp (Value varchar(2))


insert #Temp
exec ( 'select * from ' + @Param )

SET NOCOUNT OFF

select *
from sysobjects
where type in ( select Value from #Temp )

END
GO
-- вызов процедуры
create table #MyList (Item varchar(2))

insert #MyList values ('S')
insert #MyList values ('V')
insert #MyList values ('P')
GO
exec Test1 '#MyList'
GO
drop table #MyList

GO


2. Работать с массивами так, как это принято в других языках программирования.
Такое желание возникает у новичков в SQL. Таблица - это тот же массив, только представленный в "плоском" виде. Вот так будет выглядеть работа с таблицей как с трехмерным массивом:
use tempdb

GO
CREATE TABLE Array1 (i int, j int, k int, Value decimal)
GO
DECLARE @i int, @j int, @k int
SET @i=0
WHILE @i<10
BEGIN
SET @j=0
WHILE @j<10
BEGIN
SET @k=0
WHILE @k<10
BEGIN
INSERT Array1 VALUES(@i, @j, @k, RAND()*10000)

SET @k=@k+1
END
SET @j=@j+1
END
SET @i=@i+1
END
GO
SELECT * FROM Array1
GO
DROP TABLE Array1

GO

Писать такой код нет никакой надобности. Средствами языка SQL можно делать гораздо более сложные операции над таблицами. И все эти операции производятся с потрясающей быстротой, потому что это является основой SQL.
Надеюсь, Вы поняли, что я хотел сказать. Если у Вас появилась потребность в массивах только для того, чтобы поработать с ними как в Pascal или C, то это означает, что Вы не прониклись духом реляционных баз данных.

3. Хранить массивы в строках таблицы.

1) У Вас появилась необходимость хранить для каждой записи массив одинаковой структуры.
Ничего кроме денормализации базы данных, усложнения кода и замедления обработки данных это не даст. Для таких массивов создается отдельная таблица с добавлением уникального кода строки главной таблицы.
Например, не надо хранить в таблице клиентов движение по ним. Движение выносится в отдельную таблицу.

2) У Вас появилась необходимость хранить для каждой записи массивы разной структуры.
Это равносильно хранению в таблице объектов. Для хранения таких массивов используйте возможности XML или пишите свой "парсер". Хранить их придется в виде varchar, text, varbinary или image в зависимости от предполагаемой величины массивов.
Надеюсь, Вы нашли эту информацию полезной. Вопросы, предложения и пожелания шлите на адрес sql@likor.ru
С уважением, Сергей Кошкин.
Архив рассылки смотрите на сайте Рассылки http://sql.softmatics.ru/
Рейтинг@Mail.ru

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное