Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Что можно использовать вместо курсора  [new]
Nick_Sharp
Member

Откуда:
Сообщений: 5
Здравствуйте. Считаю себя новичком в работе с БД, поэтому прошу совета. Есть значения в количестве от 1 до 1000 (2000 - не важно) и есть База, в которой содержится куча таблиц с 7-30 млн записей в каждой. Как можно проверить вхождение этих значений в этой куче таблиц не прибегая к помощи курсора (такую задачу нужно решать периодически) и если они там встречаются, то выгрузить информацию в отдельную таблицу? Можно ли использовать для этой цели индексированные представления и даст ли это какой либо выигрыш по скорости выполнения запроса?

Работаю в среде MSSQL Server 2005.
12 май 17, 19:05    [20477475]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
s_ustinov
Member

Откуда: Munchen, DE
Сообщений: 2169
Nick_Sharp
Есть значения в количестве от 1 до 1000 (2000 - не важно) и есть База, в которой содержится куча таблиц с 7-30 млн записей в каждой. Как можно проверить вхождение этих значений в этой куче таблиц не прибегая к помощи курсора (такую задачу нужно решать периодически) и если они там встречаются, то выгрузить информацию в отдельную таблицу?

Извините, а как можно решать эту задачу с помощью курсора?
12 май 17, 21:21    [20477760]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
invm
Member

Откуда: Москва
Сообщений: 9127
1. Создать представление:
create view dbo.[Куча таблиц]
as
select
 'Таблица1' as table_name, id, Value
from
 Таблица1

union all

select
 'Таблица2', id, Value
from
 Таблица2

union all

select
 'ТаблицаN', id, Value
from
 ТаблицаN;

2. Сам запрос:
insert into dbo.[Отдельная таблица]
 (...)
 select
  t.table_name, t.id, t.Value
 from
  dbo.[Куча таблиц] t
 where
  t.Value between 1 and 1000;

ЗЫ: Для каждой таблицы из "кучи" сделать индекс по Value.
12 май 17, 22:28    [20477913]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Nick_Sharp
Member

Откуда:
Сообщений: 5
s_ustinov, ну я вот так делаю:

DECLARE @var1 varchar(200), @date_from datetime, @date_to datetime
DECLARE @tmp1 varchar(200), @tmp2 varchar(200), @tmp3 varchar(500)

Declare My_cursor cursor local FOR
Select Phone From dbo.MyValue

Open My_cursor
Fetch next from My_cursor into @var1
while @@Fetch_STATUS=0
Begin

SET @date_from = CAST('2016-06-01' AS datetime)
SET @date_to = CAST('2017-05-04' AS datetime)

WHILE @date_from < @date_to
BEGIN
set @tmp1 = CONVERT(CHAR(10),@date_from,120)
set @tmp2 = REPLACE(@tmp1, '-', '_')
set @tmp3 = 'insert into MyTemp (...)
select (...)
from T_' + @tmp2 + '
where [Value] =''' + @var1 + ''''
EXEC(@tmp3)
SET @date_from = DATEADD(day, 1, @date_from)
END

Fetch next from My_cursor into @var1
END
Close My_cursor
Deallocate My_cursor
15 май 17, 09:25    [20481089]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
INNER JOIN
15 май 17, 09:37    [20481125]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Nick_Sharp
Member

Откуда:
Сообщений: 5
INVM, спасибо за Ваш ответ, правда я не все понял :-)

Value - это значения которые мне надо найти в таблицах, правильно?

В представлении:

create view dbo.[Куча таблиц]
as
select
 'Таблица1' as table_name, id, Value
- название таблицы в кавычках это именно такой синтаксис или Вы так просто написали?
Еще такой момент - а если периодически появляются новые таблицы, нужно будет изменять представление? Или же проще создать таблицу, в которую будут записываться названия таблиц, а потом осуществлять выборку таблиц по ней?

В запросе:

where
  t.Value between 1 and 1000;
- здесь Вы имеете ввиду сами значения - от 1 до 1000? Просто они могут быть самые разные, а их количество варьируется от 1 до 1000. В этом случае наверное нужно искомые значения забивать в отдельный столбец и проходить по нему, а как это можно сделать? Или же поиск может осуществляться по другому?

А индекс для каждой таблицы из "кучи" некластеризованный создавать, если порядок следования записей лучше не нарушать?
15 май 17, 09:57    [20481172]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
Ох ты ж, еще и динамические запросы. Ну тогда так
DECLARE
  @tsql VARCHAR(MAX) = ''
;
WITH
dt AS (
  SELECT
    [date] = CONVERT( DATE, '20160601' )
  UNION ALL
  SELECT
    [date] = DATEADD( DAY, 1, dt.[date] )
  FROM
    dt
  WHERE
    dt.[date] < CONVERT( DATE, '20170504' )
),
tt AS (
SELECT
  [date],
  [table] = REPLACE( CONVERT( CHAR(10), [date], 120 ), '-', '_' )
FROM
  dt
)
SELECT
  @tsql = (
SELECT
[text()] = '
INSERT INTO 
  MyTemp (
    ...
  ) WITH ( TABLOCKX )
SELECT 
  ...
FROM 
  [dbo].[MyValue] v 
  INNER JOIN ' + QUOTENAME( [table] ) + ' t ON (
        t.[Value] = v.[Phone] );'
FROM
  tt
ORDER BY
  [date]
FOR 
  XML PATH ( '' ), TYPE
).value( '.', 'VARCHAR(MAX)' )
OPTION (
  MAXRECURSION 0 )
;
--SELECT @tsql
EXECUTE sp_executesql @tsql;
15 май 17, 10:01    [20481189]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Nick_Sharp
Member

Откуда:
Сообщений: 5
Руслан Дамирович
Ох ты ж, еще и динамические запросы. Ну тогда так
DECLARE
  @tsql VARCHAR(MAX) = '';

WITH
dt AS (
         SELECT [date] = CONVERT( DATE, '20160601' )
         UNION ALL
         SELECT [date] = DATEADD( DAY, 1, dt.[date] )
         FROM dt
         WHERE dt.[date] < CONVERT( DATE, '20170504' )
         ),
tt AS (
         SELECT [date], [table] = REPLACE( CONVERT( CHAR(10), [date], 120 ), '-', '_' )
         FROM dt
        )
SELECT @tsql = (
                SELECT [text()] = 'INSERT INTO MyTemp (...) WITH ( TABLOCKX )
                                   SELECT ...
                                   FROM [dbo].[MyValue] v 
                                      INNER JOIN ' + QUOTENAME( [table] ) + ' t ON (t.[Value] = v.[Phone] );'
                FROM tt
                ORDER BY [date]
                FOR XML PATH ( '' ), TYPE
               ).value( '.', 'VARCHAR(MAX)')
OPTION (MAXRECURSION 0);

--SELECT @tsql
EXECUTE sp_executesql @tsql;


Спасибо, Руслан Дамирович, буду разбираться с Вашим запросом :)
15 май 17, 10:47    [20481317]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
invm
Member

Откуда: Москва
Сообщений: 9127
Nick_Sharp
Value - это значения которые мне надо найти в таблицах, правильно?
Да.
Nick_Sharp
название таблицы в кавычках это именно такой синтаксис или Вы так просто написали?
Это столбец, позволяющий узнать какой таблице принадлежит запись.
Nick_Sharp
если периодически появляются новые таблицы, нужно будет изменять представление?
Да.
Nick_Sharp
Просто они могут быть самые разные, а их количество варьируется от 1 до 1000
Значит значения нужно сложить во временную таблицу и соединить ее с представлением.
Nick_Sharp
А индекс для каждой таблицы из "кучи" некластеризованный создавать, если порядок следования записей лучше не нарушать?
Порядка следования записей не существует.
Если из таблиц извлекается только столбец Value, то тип индекса не важен.
15 май 17, 11:11    [20481401]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
Nick_Sharp
Member

Откуда:
Сообщений: 5
invm
Порядка следования записей не существует.
Если из таблиц извлекается только столбец Value, то тип индекса не важен.

А если не только столбец Value, но и другая информация?
15 май 17, 15:30    [20482163]     Ответить | Цитировать Сообщить модератору
 Re: Что можно использовать вместо курсора  [new]
invm
Member

Откуда: Москва
Сообщений: 9127
Nick_Sharp
А если не только столбец Value, но и другая информация?
create index ... on ... (Value) include (другай информация)
15 май 17, 15:53    [20482251]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить