Ответ 1
Вы можете использовать Пользовательская функция или view вместо процедуры.
Процедура может возвращать несколько наборов результатов, каждая со своей собственной схемой. Он не подходит для использования в выражении SELECT
.
У меня есть хранимая процедура, которая возвращает строки:
CREATE PROCEDURE MyProc
AS
BEGIN
SELECT * FROM MyTable
END
Моя фактическая процедура немного сложнее, поэтому необходим sproc.
Можно ли выбрать выход, вызвав эту процедуру?
Что-то вроде:
SELECT * FROM (EXEC MyProc) AS TEMP
Мне нужно использовать SELECT TOP X
, ROW_NUMBER
и дополнительное предложение WHERE
для размещения моих данных, и я действительно не хочу передавать эти значения в качестве параметров.
Вы можете использовать Пользовательская функция или view вместо процедуры.
Процедура может возвращать несколько наборов результатов, каждая со своей собственной схемой. Он не подходит для использования в выражении SELECT
.
Вы должны посмотреть на эту замечательную статью Эрланда Соммарскога:
В нем перечислены все доступные параметры для вашего сценария.
Вы можете
... sql....
Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params
Select * from @T Where ...
Вы либо хотите функцию Table-Valued или вставьте EXEC во временную таблицу:
INSERT INTO #tab EXEC MyProc
Вы должны прочитать о OPENROWSET и OPENQUERY
SELECT *
INTO #tmp FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
Нет необходимости использовать временную таблицу.
Это мое решение
SELECT * FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue
Вы можете копировать выходные данные из sp в временную таблицу.
CREATE TABLE #GetVersionValues
(
[Index] int,
[Name] sysname,
Internal_value int,
Character_Value sysname
)
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion'
SELECT * FROM #GetVersionValues
drop TABLE #GetVersionValues
Вам нужно объявить тип таблицы, который содержит то же количество столбцов, возвращаемых вашей процедурой хранилища. Типы данных столбцов в типе таблицы и столбцы, возвращаемые процедурами, должны быть одинаковыми
declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)
Затем вам нужно вставить результат своей хранимой процедуры в свой тип таблицы, который вы только что определили
Insert into @MyTableType
EXEC [dbo].[MyStoredProcedure]
В конце просто выберите из своего типа таблицы
Select * from @MyTableType
Вы можете немного обмануть OPENROWSET:
SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...
Это все равно будет запускать весь SP каждый раз, конечно.
используйте OPENQUERY и befor Execute set 'SET FMTONLY OFF; SET NOCOUNT ON; '
Попробуйте этот пример кода:
SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE [database].[dbo].[storedprocedure] value,value ')
Похоже, вам просто нужно использовать view. Представление позволяет запросить представление в виде таблицы, чтобы он, вид, мог быть запрошен.
Попробуйте преобразовать свою процедуру в Inline Function, которая возвращает таблицу следующим образом:
CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)
И тогда вы можете назвать его
SELECT * FROM MyProc()
У вас также есть возможность передавать параметры функции следующим образом:
CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ... )
И назовите его
SELECT * FROM FuncName ( @para1 , @para2 )
Если "DATA ACCESS" false,
EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE
после
SELECT * FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')
он работает.
Если ваш сервер называется SERVERX, например, так я это сделал...
EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE;
DECLARE @CMD VARCHAR(1000);
DECLARE @StudentID CHAR(10);
SET @StudentID = 'STUDENT01';
SET @CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + @StudentID + ''') WHERE SOMEFIELD = SOMEVALUE';
EXEC (@CMD);
Чтобы проверить это, я прокомментировал командную строку EXEC()
и заменил ее на SELECT @CMD
, чтобы просмотреть команду, прежде чем пытаться ее выполнить! Это должно было убедиться, что все правильное количество одиночных кавычек было в нужном месте.: -)
Я надеюсь, что это поможет кому-то.
Для простоты и для повторного запуска я использовал систему StoredProcedure "sp_readerrorlog" для получения данных:
-----USING Table Variable
DECLARE @tblVar TABLE (
LogDate DATETIME,
ProcessInfo NVARCHAR(MAX),
[Text] NVARCHAR(MAX)
)
INSERT INTO @tblVar Exec sp_readerrorlog
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM @tblVar
-----(OR): Using Temp Table
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;
CREATE TABLE #temp (
LogDate DATETIME,
ProcessInfo NVARCHAR(55),
Text NVARCHAR(MAX)
)
INSERT INTO #temp EXEC sp_readerrorlog
SELECT * FROM #temp