Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Использовать результат динамического запроса хранимой процедуры в запросе или VIEW / 25 сообщений из 27, страница 1 из 2
26.09.2018, 11:19
    #39708296
4d_monster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
При переводе бэкенда базы с MS Access на SQL server 2017 с сохранением фронтенда на MDB, помимо прочих возникла проблема с перекрёстными запросами и зависимыми от них запросами.

Для самих перекрёстных запросов написана базовая функция msrTransformAsAccessDo, которая используя динамический SQL возвращает набор записей:
msrTransformAsAccessDo
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
CREATE PROCEDURE [dbo].[msrTransformAsAccessDo]
	@TRANSFORM_Function nvarchar(max),
	@TRANSFORM_Field nvarchar(max),
	@SQL_SELECT nvarchar(max),
	@SQL_FROM_WHERE nvarchar(max),
	@SQL_GROUPBY_HAVING_ORDERBY nvarchar(max),
	@PIVOTBY nvarchar(max) 
AS
BEGIN
	SET NOCOUNT ON
	DECLARE @DynSQL nvarchar(max)
	SET @DynSQL = N' SELECT DISTINCT ' + @PIVOTBY + ' as key_value into ##pivoting ' + @SQL_FROM_WHERE + ' ORDER BY ' + @PIVOTBY
	DROP TABLE IF EXISTS ##pivoting
	EXEC (@DynSQL)
	DECLARE @Values nvarchar(max) = N''
	DECLARE @tmpStr nvarchar(max)
	DECLARE @rsk CURSOR         
	SET @rsk = CURSOR SCROLL
		FOR	
			select key_value from ##pivoting
	OPEN @rsk         
		FETCH NEXT FROM @rsk INTO @tmpStr
		WHILE @@FETCH_STATUS = 0
			BEGIN
				SET @Values = @Values + ', ' + @TRANSFORM_Function + '(Case When convert(nvarchar,' + @PIVOTBY + ')=convert(nvarchar,''' + @tmpStr + ''') Then ' + @TRANSFORM_Field + ' Else Null End) AS [' + @tmpStr + '] '
				FETCH NEXT FROM @rsk INTO @tmpStr
			END
	CLOSE @rsk
	DROP TABLE IF EXISTS ##pivoting
	SET @DynSQL = @SQL_SELECT + @Values + @SQL_FROM_WHERE + @SQL_GROUPBY_HAVING_ORDERBY
	EXEC (@DynSQL)
END


И для каждого из перекрёстных запросов по функции обёртке с вызовом:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE PROCEDURE [dbo].[TestPIVOT]
AS
BEGIN
	SET NOCOUNT ON;
	EXEC msrTransformAsAccessDo	 
	  'Sum', 'qty'
	  ,'SELECT SeenAt, stockid ', 'FROM tbl_test ', 'GROUP BY SeenAt, stockid ' 
	  , 'shelfid'
END


Тестовая таблица
tbl_test
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
CREATE TABLE tbl_test
(
    SeenAt  date,
    stockid  int,
    shelfid  int,
    qty  float
);

INSERT INTO tbl_test
(
    SeenAt,
    stockid,
    shelfid,
    qty
) VALUES
('2018-03-01',1000,1,24.8),

('2018-03-02',1000,1,26.2),
('2018-03-02',1000,2,11.3),
('2018-03-02',1000,3,45.0),

('2018-03-03',1000,1,27.8),
('2018-03-03',1000,3,87.1),

('2018-03-04',1000,1,28.8),
('2018-03-04',1000,2,31.8),

('2018-03-05',1000,1,21.8),
('2018-03-06',1000,4,23.8),

('2018-03-01',2000,1,30.89),
('2018-03-02',2000,2,33.00),
('2018-03-03',2000,1,34.8),
('2018-03-04',2000,2,34.2),
('2018-03-05',2000,1,33.8),
('2018-03-06',2000,2,43.8);


Соответственно результат самого перекрёстного запроса получить легко:
Код: sql
1.
EXECUTE [dbo].[TestPIVOT] 


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
SeenAt  	stockid	1	2	3	4
2018-03-01	1000	24.8	NULL	NULL	NULL
2018-03-02	1000	26.2	11.3	45	NULL
2018-03-03	1000	27.8	NULL	87.1	NULL
2018-03-04	1000	28.8	31.8	NULL	NULL
2018-03-05	1000	21.8	NULL	NULL	NULL
2018-03-06	1000	NULL	NULL	NULL	23.8
2018-03-01	2000	30.89	NULL	NULL	NULL
2018-03-02	2000	NULL	33	NULL	NULL
2018-03-03	2000	34.8	NULL	NULL	NULL
2018-03-04	2000	NULL	34.2	NULL	NULL
2018-03-05	2000	33.8	NULL	NULL	NULL
2018-03-06	2000	NULL	43.8	NULL	NULL
Но в Access'е этот результат используется в JOIN'ах множества других запросов.
В FAQ :Select из результата выполнения хранимой процедуры описано 2 варианта. Первый - "Оформить хранимую процедуру как функцию", не подходит т.к. количество столбцов неизвестно, второй - "Получить набор через временную таблицу" - потребует превратить все зависимые запросы в хранимые процедуры с динамическим SQL и потребует написания сложной программы создающей тексты этих процедур.

Подскажите, какие есть ещё варианты?
...
Рейтинг: 0 / 0
26.09.2018, 11:29
    #39708302
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
4d_monster,

OPENQUERY
но смысл перехода с таким подходом теряется
...
Рейтинг: 0 / 0
26.09.2018, 12:06
    #39708338
4d_monster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
TaPaK,

К сожалению OPENQUERY и openrowset не работают с динамическим SQL:
Код: sql
1.
select * from openquery ( [LOOPBACK],  'exec testDB.dbo.[TestPIVOT]' )


Код: plaintext
1.
Msg 11514, Level 16, State 1, Procedure sys.sp_describe_first_result_set, Line 1 [Batch Start Line 0]
Не удалось определить метаданные, поскольку инструкция "EXEC (@DynSQL)" в процедуре "msrTransformAsAccessDo" содержит динамический код SQL.  Рекомендуется использовать предложение WITH RESULT SETS, чтобы явно описать результирующий набор.
...
Рейтинг: 0 / 0
26.09.2018, 14:30
    #39708489
KRS544
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Код: sql
1.
2.
set @Query= 'ваш запрос'
EXEC ('select * from openquery ( [LOOPBACK],  '''+@Query+''' )')
...
Рейтинг: 0 / 0
26.09.2018, 14:33
    #39708492
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Есть ажно три пути.
1. Разучить таки родной pivot MS SQL.
2. В процедуре засовывать результат во временную таблицу и возвращать селект из времянки.
3. Забить на это фуфло.
...
Рейтинг: 0 / 0
26.09.2018, 14:59
    #39708513
4d_monster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
KRS544,
А как этот результат использовать в качестве источника для SELECT?

aleks222,

1. А где прочитать как родной pivot MS SQL поддерживает динамические столбцы?
2. этот вариант описан в вопросе, он резервный.
3. это ещё недостаточно большая проблема, чтобы отказываться от SQL server
...
Рейтинг: 0 / 0
26.09.2018, 15:01
    #39708515
KRS544
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
4d_monsterKRS544,
А как этот результат использовать в качестве источника для SELECT?


insert into Table
exec ('...')
...
Рейтинг: 0 / 0
26.09.2018, 15:13
    #39708529
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
не хочу создавать тему, спрошу здесь, т.к. очень похоже

Есть хранимые процедуры, возвращающие таблицу, у процедур могут быть параметры, менять процедуры нельзя
нужно получить возможность делать SELECT * FROM <процедура> из клиентов,
т.е. процедуру можно обернуть любым скриптом, но клиент не может выполнять скрипты, только запросы

попробовал обернуть в функцию с временной таблицей но получил
1) [Code: 2772, SQL State: S1000] Cannot access temporary tables from within a function.
...
Рейтинг: 0 / 0
26.09.2018, 16:26
    #39708616
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikне хочу создавать тему, спрошу здесь, т.к. очень похожеА предложенное решение вам не подходит? Или вы не прочитали ответы?
...
Рейтинг: 0 / 0
26.09.2018, 17:48
    #39708707
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
alexeyvgSintetikне хочу создавать тему, спрошу здесь, т.к. очень похожеА предложенное решение вам не подходит? Или вы не прочитали ответы?
читал, которое?
...
Рейтинг: 0 / 0
27.09.2018, 02:12
    #39708953
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikalexeyvgпропущено...
А предложенное решение вам не подходит? Или вы не прочитали ответы?
читал, которое?Вот это:
Код: sql
1.
select * from openquery ( [LOOPBACK],  'exec testDB.dbo.[TestPIVOT]' )


Если, конечно, у вас нет динамического SQL. Но вы про него не писали.
Если есть, то решения не существует.
...
Рейтинг: 0 / 0
27.09.2018, 02:14
    #39708954
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikпопробовал обернуть в функцию с временной таблицей но получил
1) [Code: 2772, SQL State: S1000] Cannot access temporary tables from within a function.В функции можно использовать таблицы-переменные.
...
Рейтинг: 0 / 0
27.09.2018, 10:47
    #39709099
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
alexeyvgSintetikпропущено...

читал, которое?Вот это:
Код: sql
1.
select * from openquery ( [LOOPBACK],  'exec testDB.dbo.[TestPIVOT]' )


Если, конечно, у вас нет динамического SQL. Но вы про него не писали.
Если есть, то решения не существует.
динамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
...
Рейтинг: 0 / 0
27.09.2018, 10:49
    #39709102
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikдинамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
а нет, значит в другом примере видел, когда рыскал в поисках решения
...
Рейтинг: 0 / 0
27.09.2018, 11:00
    #39709119
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
SintetikSintetikдинамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
а нет, значит в другом примере видел, когда рыскал в поисках решенияНет, это для OPENDATASOURCE нужно, да и то не всегда.
А для OPENQUERY никогда не нужно.
...
Рейтинг: 0 / 0
27.09.2018, 11:10
    #39709135
DaniilSeryi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikне хочу создавать тему, спрошу здесь, т.к. очень похоже

Есть хранимые процедуры, возвращающие таблицу, у процедур могут быть параметры, менять процедуры нельзя
нужно получить возможность делать SELECT * FROM <процедура> из клиентов,
т.е. процедуру можно обернуть любым скриптом, но клиент не может выполнять скрипты, только запросы

попробовал обернуть в функцию с временной таблицей но получил
1) [Code: 2772, SQL State: S1000] Cannot access temporary tables from within a function.

FAQ почитайте: http://www.sql.ru/faq/faq_topic.aspx?fid=416
...
Рейтинг: 0 / 0
27.09.2018, 16:18
    #39709396
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
alexeyvgSintetikпропущено...

читал, которое?Вот это:
Код: sql
1.
select * from openquery ( [LOOPBACK],  'exec testDB.dbo.[TestPIVOT]' )


Если, конечно, у вас нет динамического SQL. Но вы про него не писали.
Если есть, то решения не существует.

автор[Code: 7202, SQL State: S1000] Could not find server 'LOOPBACK' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
...
Рейтинг: 0 / 0
27.09.2018, 16:20
    #39709399
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikalexeyvgпропущено...
Вот это:
Код: sql
1.
select * from openquery ( [LOOPBACK],  'exec testDB.dbo.[TestPIVOT]' )


Если, конечно, у вас нет динамического SQL. Но вы про него не писали.
Если есть, то решения не существует.

автор[Code: 7202, SQL State: S1000] Could not find server 'LOOPBACK' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
линк кто за вас создать? справку о команде тоже лень прочитать? Сразу на форум строчить
...
Рейтинг: 0 / 0
27.09.2018, 16:48
    #39709424
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikавтор[Code: 7202, SQL State: S1000] Could not find server 'LOOPBACK' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.Да, вот что написано, то и нужно сделать.
Или в графическом интерфейсе, если вам так удобнее.
...
Рейтинг: 0 / 0
27.09.2018, 17:09
    #39709430
Sintetik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
TaPaKлинк кто за вас создать? справку о команде тоже лень прочитать? Сразу на форум строчить
я полагал, что есть по умолчанию стандартный линк сам на себя с таким именем LOOPBACK
...
Рейтинг: 0 / 0
27.09.2018, 17:48
    #39709447
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Sintetikя полагал, что есть по умолчанию стандартный линк сам на себя с таким именем LOOPBACKНет, увы.
Просто непонятно, зачем он нужен, ведь любой динамический запрос можно сделать просто в EXEC, всё таки такое редко встречается, что нужно непременно слово SELECT.
...
Рейтинг: 0 / 0
27.09.2018, 23:48
    #39709582
AndrF
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
4d_monster,

Как вариант - пускай ваша процедура только строит строку запроса, но не запускает, а просто возвращает вам ее, ну а далее вы в динамике делаете с ней что хотите...
...
Рейтинг: 0 / 0
28.09.2018, 08:40
    #39709640
4d_monster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
AndrF,

Получается есть только два варианта:
1. создавать временные таблицы
2. использовать динамический текст запроса.

И оба варианта требуют превращения запросов, зависимых от перекрёстного, в хранимые процедуры.

Проверю, какой проще в реализации и выберу его.
...
Рейтинг: 0 / 0
28.09.2018, 12:22
    #39709768
Ivan Durak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
4d_monsterAndrF,

Получается есть только два варианта:
1. создавать временные таблицы
2. использовать динамический текст запроса.

И оба варианта требуют превращения запросов, зависимых от перекрёстного, в хранимые процедуры.

Проверю, какой проще в реализации и выберу его.
Есть еще самый нормальный вариант - изменить процедуру внутри, чтобы она результат сама в таблицу писала
Кто ж вам доктор, что у вас по нормальному нельзя
...
Рейтинг: 0 / 0
28.09.2018, 12:55
    #39709798
4d_monster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
Ivan Durak4d_monsterAndrF,

Получается есть только два варианта:
1. создавать временные таблицы
2. использовать динамический текст запроса.

И оба варианта требуют превращения запросов, зависимых от перекрёстного, в хранимые процедуры.

Проверю, какой проще в реализации и выберу его.
Есть еще самый нормальный вариант - изменить процедуру внутри, чтобы она результат сама в таблицу писала
Поля не определены заранее ведь это динамический перекрёстный запрос, поэтому ваше предложение это 1 пункт.

Ivan DurakКто ж вам доктор, что у вас по нормальному нельзя
"Legacy" знаете? Тамошние мы.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Использовать результат динамического запроса хранимой процедуры в запросе или VIEW / 25 сообщений из 27, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]