powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
27 сообщений из 27, показаны все 2 страниц
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708296
Фотография 4d_monster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При переводе бэкенда базы с 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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708302
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4d_monster,

OPENQUERY
но смысл перехода с таким подходом теряется
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708338
Фотография 4d_monster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708489
KRS544
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
set @Query= 'ваш запрос'
EXEC ('select * from openquery ( [LOOPBACK],  '''+@Query+''' )')
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708492
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть ажно три пути.
1. Разучить таки родной pivot MS SQL.
2. В процедуре засовывать результат во временную таблицу и возвращать селект из времянки.
3. Забить на это фуфло.
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39708513
Фотография 4d_monster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KRS544,
А как этот результат использовать в качестве источника для SELECT?

aleks222,

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


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

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

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


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

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


Если, конечно, у вас нет динамического SQL. Но вы про него не писали.
Если есть, то решения не существует.
динамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709102
Sintetik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sintetikдинамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
а нет, значит в другом примере видел, когда рыскал в поисках решения
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709119
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SintetikSintetikдинамического нет, но в этом варианте нужно в строку вызова передавать логин-пароль, по крайней мере в примере выше так было, поэтому я откинул этот вариант, или можно обойтись без передачи?
а нет, значит в другом примере видел, когда рыскал в поисках решенияНет, это для OPENDATASOURCE нужно, да и то не всегда.
А для OPENQUERY никогда не нужно.
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709135
DaniilSeryi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709396
Sintetik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709399
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709424
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709430
Sintetik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKлинк кто за вас создать? справку о команде тоже лень прочитать? Сразу на форум строчить
я полагал, что есть по умолчанию стандартный линк сам на себя с таким именем LOOPBACK
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709447
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sintetikя полагал, что есть по умолчанию стандартный линк сам на себя с таким именем LOOPBACKНет, увы.
Просто непонятно, зачем он нужен, ведь любой динамический запрос можно сделать просто в EXEC, всё таки такое редко встречается, что нужно непременно слово SELECT.
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709582
AndrF
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4d_monster,

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

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

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

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

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

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

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

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

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

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

Ivan DurakКто ж вам доктор, что у вас по нормальному нельзя
"Legacy" знаете? Тамошние мы.
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709837
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как вариант - преобразуйте в функцию, возвращающую XML.
И, соответственно, потом парсите этот xml в CTE, ну и вяжитесь с этой CTE.
...
Рейтинг: 0 / 0
Использовать результат динамического запроса хранимой процедуры в запросе или VIEW
    #39709856
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4d_monsterПолучается есть только два варианта:
1. создавать временные таблицы
2. использовать динамический текст запроса.
Если есть линкованый сервер к Акцессу, то можно обойтись без динамики, - использовать Акс-вский TRANSFORM, но таблицы в запросе будут серверные
типа такого
Код: sql
1.
2.
3.
4.
5.
6.
7.
select * from openquery ([ACCESS],'
TRANSFORM Sum(t.val) AS [Sum-val]
SELECT t.id
FROM [ODBC;DRIVER=SQL Server;SERVER=(local);Trusted_Connection=Yes;DATABASE=tempdb].t
GROUP BY t.id
PIVOT t.y
')


... или даже без линк.сервера, через OPENROWSET
Главное что бы был установленный провайдер, и где-то на сервере "валялся" файл Акса.
Код: 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.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
use tempdb
go

create table t (y int, id int, val int)
go

insert into t 
select 2012, 1, 10 union all
select 2012, 1, 10 union all
select 2012, 1, 10 union all
select 2013, 1, 10 union all
select 2013, 1, 10 union all
select 2013, 2, 10
go


select *
   FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
      'C:\test.mdb';
      'admin';'',
'
TRANSFORM Sum(t.val) AS [Sum-val]
SELECT t.id
FROM [ODBC;DRIVER=SQL Server;SERVER=(local);Trusted_Connection=Yes;DATABASE=tempdb].t
GROUP BY t.id
PIVOT t.y
'
);
go

insert into t 
select 2014, 1, 10 union all
select 2014, 1, 10 union all
select 2015, 1, 10 union all
select 2016, 1, 10 union all
select 2017, 1, 10 union all
select 2018, 2, 10

go

select *
   FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
      'C:\test.mdb';
      'admin';'',
'
TRANSFORM Sum(t.val) AS [Sum-val]
SELECT t.id
FROM [ODBC;DRIVER=SQL Server;SERVER=(local);Trusted_Connection=Yes;DATABASE=tempdb].t
GROUP BY t.id
PIVOT t.y
'
);
go

drop table t


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


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