Используйте SQL для фильтрации результатов хранимой процедуры - PullRequest
29 голосов
/ 02 апреля 2010

Я смотрел на другие вопросы о переполнении стека, связанные с этим вопросом, но ни один из них, казалось, не ответил на этот вопрос четко.

У нас есть системная хранимая процедура sp_who2, которая возвращает результирующий набор информации для всех запущенных процессов на сервере. Я хочу отфильтровать данные, возвращаемые хранимой процедурой; концептуально, я мог бы сделать это так:

SELECT * FROM sp_who2
WHERE login='bmccormack'

Этот метод, тем не менее, не работает. Какова хорошая практика для достижения цели запроса возвращенных данных хранимой процедуры, предпочтительно без необходимости искать код исходной хранимой процедуры и изменять его.

Ответы [ 5 ]

31 голосов
/ 02 апреля 2010

Нет хороших способов сделать это. Это ограничение хранимых процедур. Ваши варианты:

  1. Переключите процедуру на Пользовательскую функцию . Сегодня во всем мире люди делают хранимые процедуры, которые должны быть функциями. Это проблема образования. Ваша ситуация является хорошим примером, почему. Если бы ваша процедура была вместо этого UDF, вы могли бы просто сделать следующее, именно так, как вы интуитивно думаете, вы должны быть в состоянии:

    SELECT * FROM udf_who2()
    WHERE login='bmccormack'
    
  2. Если вы действительно не можете коснуться своей процедуры, и должен сделать это в sql, то вам придется повеселиться. Сделайте другую хранимую процедуру, чтобы обернуть вашу оригинальную процедуру. Внутри вашей новой процедуры вызовите существующую процедуру и поместите значения во временную таблицу, затем выполните запрос к этой таблице с нужным фильтром и верните этот результат во внешний мир.

Начиная с SQL Server 2005, пользовательские функции - это способ инкапсуляции извлечения данных. Хранимые процедуры, наряду с представлениями, являются специальными инструментами для использования в определенных ситуациях. Они оба очень удобны в нужное время, но не лучший выбор. Некоторые могут подумать, что вышеприведенный пример (A) получает все результаты функции, а затем (B) фильтрует этот набор результатов, как подзапрос. Это не тот случай . SQL Server 2005+ оптимизирует этот запрос; если на login есть индекс, вы не увидите сканирование таблицы в плане выполнения запроса; очень эффективно.

Редактировать : Я должен добавить, что внутренности UDF похожи на внутреннюю часть SP. Если вам не хватает логики SP, которую вы хотите избежать, вы все равно можете изменить ее на функцию. Несколько раз я брал большой, страшный код процедур, который мне не хотелось понимать, и успешно переносил его в функцию. Единственная проблема будет в том случае, если процедура изменяет что-либо помимо возврата результатов; UDF не могут изменять данные в БД.

15 голосов
/ 03 февраля 2015

Возможна фильтрация временной таблицы.

-- Create tmp table from sp_who results
CREATE TABLE #TmpWho
(spid INT, ecid INT, status VARCHAR(150), loginame VARCHAR(150),
hostname VARCHAR(150), blk INT, dbname VARCHAR(150), cmd VARCHAR(150), request_id INT)
INSERT INTO #TmpWho
EXEC sp_who

-- filter temp table where spid is 52
SELECT * FROM #TmpWho
WHERE spid = 52

DROP TABLE #TmpWho
12 голосов
/ 02 апреля 2010

Вы можете сделать OPENROWSET(), но есть некоторые проблемы безопасности / производительности.

SELECT * 
FROM OPENROWSET ('SQLOLEDB', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec mystoredproc')

Традиционно добавление его во временную переменную / таблицу будет работать.

3 голосов
/ 02 апреля 2010

Поместите данные в переменную Table или Temp и отфильтруйте их.

0 голосов
/ 17 августа 2018

OPENROWSET () - это путь:

SELECT *
FROM
    OPENROWSET('SQLNCLI', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec sp_who')
WHERE loginame = 'test' AND dbname = 'Expirement';

Также перед работой необходимо включить предварительную настройку:

sp_configure 'show advanced options', 1;  
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1; 
RECONFIGURE;
GO 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...