Член моей команды проводил тест производительности и настраивал хранимые процедуры SQL и отметил, что
в том же контейнере хранимых процедур с тем же exe c разрешения для этого sp;
case 1
: вызов sql строки запроса (select) с переменными, объединениями и т. д. c ...
case 2
: построение sql строка запроса и вызов sp_execute sql с sql и всеми переданными в него параметрами
В ходе тестирования case 1
был значительно медленнее, чем case 2
. Имеет смысл, все хорошо, потому что кеширование - это то, к чему мы стремились в этом отношении.
Однако выяснилось, что предоставление пользователю разрешения на запуск хранимой процедуры в case 1
означало, что они этого не делали. необходимо явное разрешение для всех таблиц, включенных в объединенный оператор выбора, в то время как в case 2
с вызовом запроса через sp_execute sql мы должны были явно предоставить разрешение всем таблицам в sql запросе для успешной работы.
Вопросы //
Во-первых, почему ... существует конкретное c обоснование относительно почему разрешения подразумеваются и каскадируются с одним, а не с другим, и
Второе - ... Есть ли обходной путь ***?
В обоих случаях были выполнены в том же контейнере хранимых процедур без изменений в разрешениях. случай 1 работает нормально, случай 2 вызывает ошибки без прав доступа ко всем таблицам.
пример кода варианта 1
ts.tick_serv_id AS tick_serv_id
,ts.ticket_id AS ticket_id
,ts.service_id AS service_id
,ts.quantity AS quantity
,ts.employee_id AS employee_id
,ts.commission AS commission
,ts.assumed_service_date AS assumed_service_date
,ts.service_date AS service_date
,ts.status AS status
,ts.comments AS comments
,s.service_type_id AS service_type_id
,st.description AS description
,st.edit_quantity AS edit_quantity
,s.print_text AS print_text
,sr.unit_type AS unit_type
,sr.rate AS rate
FROM ticket_services ts
INNER JOIN tickets t ON t.ticket_id=ts.ticket_id
INNER JOIN services s ON ts.service_id=s.service_id
INNER JOIN service_rates sr ON ts.service_id=sr.service_id
INNER JOIN service_types st ON s.service_type_id=st.service_type_id
WHERE (tick_serv_id = @tick_serv_id OR @tick_serv_id IS NULL)
AND (ts.ticket_id = @ticket_id OR @ticket_id IS NULL)
AND (ts.service_id = @service_id OR @service_id IS NULL)
AND (ts.quantity = @quantity OR @quantity IS NULL)
AND (ts.employee_id = @employee_id OR @employee_id IS NULL)
AND (ts.commission = @commission OR @commission IS NULL)
AND (ts.assumed_service_date = @assumed_service_date OR @assumed_service_date IS NULL)
AND (ts.service_date = @service_date OR @service_date IS NULL)
AND (t.open_date BETWEEN sr.open_date AND sr.close_date)
AND (ts.status = @status OR @status = '')
AND (ts.comments = @comments OR @comments = '')
пример кода варианта 2
@tick_serv_id bigint,
@ticket_id bigint,
@service_id int,
@quantity int,
@employee_id int,
@commission float,
@assumed_service_date datetime,
@service_date datetime,
@status char(1),
@comments varchar(500)'
DECLARE @sql nvarchar(max) = N'
SELECT
ts.tick_serv_id
,ts.ticket_id
,ts.service_id
,ts.quantity
,ts.employee_id
,ts.commission
,ts.assumed_service_date
,ts.service_date
,ts.status
,ts.comments
,s.service_type_id
,st.description
,st.edit_quantity
,s.print_text AS print_text
,sr.unit_type AS unit_type
,sr.rate AS rate
FROM ticket_services ts
INNER JOIN tickets t ON t.ticket_id=ts.ticket_id
INNER JOIN services s ON ts.service_id=s.service_id
INNER JOIN service_rates sr ON ts.service_id=sr.service_id
INNER JOIN service_types st ON s.service_type_id=st.service_type_id
WHERE 1 = 1 AND (t.open_date BETWEEN sr.open_date AND sr.close_date)'
+ CASE WHEN @tick_serv_id IS NOT NULL THEN
N' AND tick_serv_id = @tick_serv_id' ELSE N'' END
+ CASE WHEN @ticket_id IS NOT NULL THEN
N' AND ts.ticket_id = @ticket_id' ELSE N'' END
+ CASE WHEN @service_id IS NOT NULL THEN
N' AND ts.service_id LIKE @service_id' ELSE N'' END
+ CASE WHEN @quantity IS NOT NULL THEN
N' AND ts.quantity = @quantity' ELSE N'' END
+ CASE WHEN @employee_id IS NOT NULL THEN
N' AND ts.emplyee_id = @employee_id' ELSE N'' END
+ CASE WHEN @commission IS NOT NULL THEN
N' AND ts.commission = @commission' ELSE N'' END
+ CASE WHEN @assumed_service_date IS NOT NULL THEN
N' AND ts.assumed_service_date = @assumed_service_date' ELSE N'' END
+ CASE WHEN @service_date IS NOT NULL THEN
N' AND ts.service_date = @service_date' ELSE N'' END
+ CASE WHEN @status <> '' THEN
N' AND ts.status = @status' ELSE N'' END
+ CASE WHEN @comments <> '' THEN
N' AND comments = @comments' ELSE N'' END
;
EXEC sys.sp_executesql @sql, @params,
@tick_serv_id
,@ticket_id
,@service_id
,@quantity
,@employee_id
,@commission
,@assumed_service_date
,@service_date
,@status
,@comments;