Начало » Использование СУБД » Microsoft SQL Server » Запрос + представление или функция, как лучше сделать?* (Задача со звездочкой) (Нужен совет сообщества.) 
	
		
		
			| Запрос + представление или функция, как лучше сделать?* (Задача со звездочкой) [сообщение #2927] | 
			Mon, 07 August 2023 10:28   | 
		 
		
			
				
				
				
					
						  
						Sanek
						 Сообщений: 8 Зарегистрирован: August 2023 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		Наткнулся на следующую проблему ... 
Дано: 
Есть представление, которое очень сложным образом раcсчитывает галочку "можно, нельзя" для каждого объекта. 
Есть CTE запрос, который поделен на блоки вроде 1й блок - найти все нужные объекты, 2й - расчитать можно или нет их показывать (обращаясь к представлению) и 3й - вывод. 
 
Что не работает:  
представление считает разрешения для всей базы, но на текущий момент появилось такое кол-во записей о правах, что представление тупо зависает, пытаясь это дело обработать. 
 
Моё решение  
Появилась мысль из представления сделать функцию и передать в нее параметры , ограничивающие кол-во обрабатываемых записей, тогда функция будет работать. Но проблема в том, что список объектов, для которых надо рассчитать доступ появляется только в 1м блоке запроса.  
По этой причине мне как-то надо засунуть результат запроса в параметр функции и все это в CTE ))) 
 
Вопроса два: 
1. Возможно ли это реализовать (и как) 
2. Может есть другой путь? 
 
Пример кода: 
 
Представление (естественно пример для понимания)
Create view Accesses as 
Select ObjectId from AccessTable where Allow=1
Запрос:
With SearchQuery AS (
Select ObjectId from Table1 where ...
) , SearchQueryExt (
Select * from SearchQuery 
union Select ObjectId from Table2 where .... 
union Select ObjectId from Table3 where ....
), FilterQuery (
Select * 
   fom SearchQueryExt s 
  join Accesses a on a.ObjectId = s.ObjectId
)
Select * 
  from TableN s
  join FilterQuery f on s.ObjectId = f.ObjectId
  
Я же хочу сделать функцию что бы было так: 
Create function Accesses (ObjctIds ????)
Select ObjectId 
  from AccessTable 
 where ObjetId in ObjctIds 
   and Allow=1
А FilterQuery  поменять на что-то вроде :
.
.
.
), FilterQuery (
Select * 
   fom SearchQueryExt s 
  join dbo.fAccesses(select ObjectId from SearchQuery) on a.ObjectId = s.ObjectId
)
.
.
.
  
Есть мысли, как это реализовать ? 
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |  
	
		
		
			| Re: Запрос + представление или функция, как лучше сделать?* (Задача со звездочкой) [сообщение #2929 является ответом на сообщение #2928] | 
			Mon, 07 August 2023 11:06    | 
		 
		
			
				
				
				
					
						  
						Sanek
						 Сообщений: 8 Зарегистрирован: August 2023 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		Если "вообще", то да, можно определить табличную переменную/собственный табличный тип данных , засунуть туда данные и потом отдельно вызвать запрос SearchQueryExt 
, но, как я говорил в вопросе: список объектов для расчёта прав появляется в результате запроса "SearchQueryExt" и хотелось бы не разбивать CTE запрос, потому, что он только в примере простой, в реальной жизни он на три страницы )
		
		
		[Обновления: Mon, 07 August 2023 11:06] Известить модератора  
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	
		
		
			| Re: Запрос + представление или функция, как лучше сделать?* (Задача со звездочкой) [сообщение #2951 является ответом на сообщение #2938] | 
			Tue, 08 August 2023 08:52    | 
		 
		
			
				
				
				
					
						  
						Sanek
						 Сообщений: 8 Зарегистрирован: August 2023 
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		нет, спасибо, пример не нужен. Идея хорошая. Но по сути она не отличается от использования табличной переменной.  
и запрос разбивается на 2 части ..  
в целом по этому пути и пошел ... 
 
я тут спросил в надежде, что может я чего не знаю и что-то уже новое придумали )) 
(давно в документацию не заглядывал) 
 
А что касается outer apply - это функция, которая вызывается на каждую строку (и это в лучшем случае) выборки, что не добавляет производительности (. 
подобные методы очень удобны, но крайне вредны ... довольно много условий необходимо соблюсти, что бы их использовать. 
 
Спасибо всем принявшим участие! 
		
		
		[Обновления: Tue, 08 August 2023 08:55] Известить модератора  
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |  
	| 
		
 |  
	
		
		
			| Re: Запрос + представление или функция, как лучше сделать?* (Задача со звездочкой) [сообщение #2954 является ответом на сообщение #2953] | 
			Tue, 08 August 2023 13:31    | 
		 
		
			
				
				
				
					
						  
						shigor
						 Сообщений: 26 Зарегистрирован: March 2023  Географическое положение: НиНо
						
					 | 
					Junior Member  | 
					 | 
		 
		 
	 | 
 
	
		выполнить можно полностью, можно отдельными кусками 
 
use tempdb
go
-- создание функции обработки списка
create function fn_get_olist(@olist xml)
returns table as return (
  select 
    olist.object.value('./@o_id', 'integer') as o_id,
    'Идентификатор объекта ' + try_cast(olist.object.value('./@o_id', 'integer') as varchar(10)) as o_newname
  from @olist.nodes('/olist/object') olist(object)
)
go
-- запрос, и это не скрипт.. его можно оформить в виде представления
;with 
   -- полный список объектов
   o_list as ( select * from (values (0, 'object 0'), (1, 'object 1'), (2, 'object 2'), (3, 'object 3'), (4, 'object 4')) v(o_id, o_name)  )
   -- ограниченный список объектов
 , o_list_selected as ( select * from o_list where (o_id % 2) = 0 )
   -- ограниченный список объектов в формате xml
 , o_list_selected_xml as ( select (select (select o_id [@o_id] from o_list_selected for xml path('object'), type) olist for xml path(''), type) olist )
 -- вызов функции с ограниченным списком объектов и получением раcчетных результатов из функции
 select o_id, o_newname from o_list_selected_xml outer apply fn_get_olist(olist) 
go
-- подчистим
drop function fn_get_olist
 
		
		
		[Обновления: Tue, 08 August 2023 13:32] Известить модератора  
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |   
Переход к форуму:
 
 Текущее время: Tue Nov 04 04:04:07 GMT+3 2025 
 Общее время, затраченное на создание страницы: 0.01615 секунд 
 |