SQL Server - ВИБІРТИ ЗДІЙСНЕНО зберігається процедура


334

У мене збережена процедура, яка повертає рядки:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

Моя фактична процедура трохи складніша, саме тому проросток необхідний.

Чи можливо вибрати вихід, зателефонувавши в цю процедуру?

Щось на зразок:

SELECT * FROM (EXEC MyProc) AS TEMP

Мені потрібно використовувати SELECT TOP X, ROW_NUMBERі додатковий WHEREпункт на сторінці мої дані, і я не хочу , щоб передати ці значення в якості параметрів.


Я не впевнений, що ви маєте намір тут зробити, тому що, виконуючи процедуру, ви отримуєте рядки назад. Це ви хочете виконати процедуру всередині оператора SELECT, щоб ви могли прив’язати її до об'єкта, що відображається на сторінці?
Raj More

1
Чи є певна причина, чому ви не хочете передавати значення як параметри? Робити це так, як ви пропонуєте, трохи неефективно - ви б вибирали більше даних, ніж потрібно, а потім не використовували б їх усі.
Марк Белл

2
Подивіться тут: sommarskog.se/share_data.html
піловер

Відповіді:


149

Замість процедури можна використовувати визначену користувачем функцію або представлення .

Процедура може повернути кілька наборів результатів, кожен зі своєю схемою. Це не підходить для використання у SELECTвиписці.


8
Крім того, якщо після перетворення в UDF вам здається, що вам потрібна семантика збереженої процедури, ви завжди можете обернути UDF процедурою.
Joel Coehoorn

що робити, нам потрібно надіслати параметри для з’єднання збережених процедур та об'єднати їх в одну велику збережену процедуру? Можна переглядати, приймати параметри, як це зберігаються процедури
mrN

3
@mrN Перегляди не приймають параметрів, але UDF.
Мехрдад Афшарі

3
Здрастуйте, мені дійсно потрібно це зробити, не перетворюючи sp на вигляд чи функцію, це можливо?
Луїс Бесерріл

2
Хоча ваша відповідь є правдивим твердженням, вона не відповідає на питання .... "ВИБІРІТЬ ЗАРАЗ, що зберігається" Що впевнене, що це не ідеально, але це те, що є ... @ Відповідь Аміра є правильною відповіддю. Або це, або питання потрібно змінити ... що здається мені трохи смішним.
Urasquirrel

202

Ти можеш

  1. створити змінну таблиці для зберігання набору результатів із збереженого протоколу, а потім
  2. вставити висновок збереженого протоколу в змінну таблиці, а потім
  3. використовувати змінну таблиці точно так само, як і будь-яку іншу таблицю ...

... пл ...

Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params 
Select * from @T Where ...

34
Проблема з INSERT #Tабо INSERT @Tполягає в тому, що INSERT EXECоператор не може бути вкладений. Якщо збережена процедура вже має INSERT EXECв ній, це не працюватиме.
MOHCTP

2
Це, мабуть, найбільш портативне рішення, найближче до базового SQL. Це також допомагає підтримувати чіткі визначення типів стовпців. Повинно бути більше подій, ніж вище.

В змінної таблиці виглядає більш корисною тут , ніж тимчасові таблиці в термінах зра перекомпіляції. Тож я згоден, ця відповідь повинна мати більше відгуків.
резнянський

76

Ви або хочете виконувати функцію "Табличне значення" або вставити EXEC у тимчасову таблицю:

INSERT INTO #tab EXEC MyProc

32
Проблема з INSERT #Tабо INSERT @Tполягає в тому, що INSERT EXECоператор не може бути вкладений. Якщо збережена процедура вже має INSERT EXECв ній, це не працюватиме.
MOHCTP

46

Ви повинні прочитати про OPENROWSET та OPENQUERY

SELECT  * 
INTO    #tmp FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')

4
Як динамічно отримати ВАШЕ ВЕРСАМЕ? Ви не можете розраховувати, що потрібно знати завжди. Не буде цього перерви кожен другий вівторок? Тож якщо у мене 100 серверів, всі з різними іменами ...
Urasquirrel

також що робити, якщо моя база даних не налаштована, щоб це дозволило?
Urasquirrel

4
Спробуйте @@ ім'я сервера, щоб отримати його динамічно
Siddhartha Gandhi

44

Потрібно оголосити тип таблиці, що містить ту саму кількість стовпців, яку повертає процедура зберігання. Типи даних стовпців типу таблиці та стовпців, повернених процедурами, повинні бути однаковими

declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)  

Потім вам потрібно вставити результат збереженої процедури у визначений вами тип таблиці

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure]

Зрештою, просто виберіть із типу таблиці

Select * from @MyTableType

Це найкраще рішення для мене, тому що вам не потрібно вказувати ім’я сервера, рядки підключення або конфігурувати будь-які пов'язані сервери для того, щоб він працював - які речі я не хочу робити, щоб просто отримати деякі дані назад. Дякую! Чудова відповідь!
Метт

Приємна відповідь ღ❤ ೋ ღ❤ღ ೋ❤ ღ
Нахід

Якщо збережена процедура є надто складною - цей метод не працює, наприклад, коли зберігається процедура використовує дві темп-таблиці.
nick_n_a

34

Не варто використовувати тимчасову таблицю.

Це моє рішення

SELECT  *  FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue

2
Для цього потрібно додати свій сервер як пов'язаний сервер до себе, але це працює як шарм! Дякую!
vaheeds

Деякі чудові застереження щодо цього: stackoverflow.com/questions/2374741/…
Кіт Адлер,

1
Хм ... я отримую помилку "Помилка 7411: Сервер" YourServerName "не налаштований для доступу до даних." Що мені потрібно змінити?
Метт

Ви додали свій сервер як пов'язаний сервер? YourServerName - це ім'я вашого сервера. Ви повинні змінити YourServerName з вашим реальним іменем сервера.
DavideDM

@Matt:sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
alexkovelsky

23

Ви можете скопіювати вихід з 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

7

використовуйте OPENQUERY і виконайте команду Execute set 'SET FMTONLY OFF; ВКЛЮЧИТИ НОКУНТ; '

Спробуйте цей зразок коду:

SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE  [database].[dbo].[storedprocedure]  value,value ')

6

Спробуйте перетворити процедуру в функцію Inline, яка повертає таблицю наступним чином:

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 )

6

Якщо "ДОСТУП ДАНИХ" помилковий,

EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE

після,

SELECT  *  FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')

це працює.


5

Ви можете трохи обдурити за допомогою OPENROWSET:

SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...

Зрозуміло, це все би запускало весь СП, звичайно.


4

Для простоти і для повторного запуску я використовував систему 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

1

Здається, що вам може знадобитися просто перегляд . Перегляд дозволяє запит представити у вигляді таблиці, щоб його, представлення, можна було запитувати.


1

Якщо, наприклад, ваш сервер називається 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на перегляд команди, перш ніж спробувати виконати її! Це було для того, щоб переконатись, що вся правильна кількість одноцитатних знань у потрібному місці. :-)

Я сподіваюся, що хтось допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.