SQL Server - PILIH DARI prosedur tersimpan

334

Saya memiliki prosedur tersimpan yang mengembalikan baris:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

Prosedur saya yang sebenarnya sedikit lebih rumit, itulah mengapa sproc diperlukan.

Apakah mungkin untuk memilih output dengan memanggil prosedur ini?

Sesuatu seperti:

SELECT * FROM (EXEC MyProc) AS TEMP

Saya perlu menggunakan SELECT TOP X,, ROW_NUMBERdan WHEREklausa tambahan untuk halaman data saya, dan saya tidak benar-benar ingin meneruskan nilai-nilai ini sebagai parameter.

jonathanpeppers
sumber
Saya tidak yakin apa yang ingin Anda lakukan di sini karena ketika Anda menjalankan prosedur, Anda mendapatkan kembali baris. Apakah Anda ingin menjalankan prosedur di dalam pernyataan SELECT sehingga Anda dapat mengikatnya ke objek yang dapat di-page?
Raj More
1
Apakah ada alasan khusus mengapa Anda tidak ingin meneruskan nilai sebagai parameter? Untuk melakukannya dengan cara yang Anda sarankan agak tidak efisien - Anda akan memilih lebih banyak data daripada yang Anda butuhkan, dan kemudian tidak menggunakan semuanya.
Mark Bell
2
Lihatlah di sini: sommarskog.se/share_data.html
pylover

Jawaban:

149

Anda dapat menggunakan fungsi yang ditentukan pengguna atau tampilan alih-alih prosedur.

Prosedur dapat mengembalikan beberapa set hasil, masing-masing dengan skema sendiri. Itu tidak cocok untuk digunakan dalam SELECTpernyataan.

Mehrdad Afshari
sumber
8
Selain itu, jika setelah mengkonversi ke UDF Anda menemukan Anda memerlukan semantik prosedur tersimpan Anda selalu dapat membungkus UDF dengan prosedur.
Joel Coehoorn
bagaimana jika, kita perlu mengirim parameter ke mulple procedure yang tersimpan dan menggabungkannya menjadi satu prosedur besar yang tersimpan? Dapat melihat, mengambil parameter, seperti prosedur tersimpan tidak
mrN
3
@mrN Tampilan tidak mengambil parameter, tetapi UDF melakukannya.
Mehrdad Afshari
3
Halo, saya benar-benar perlu melakukan ini tanpa mengubah sp ke tampilan atau fungsi, apakah mungkin?
Luis Becerril
2
Meskipun jawaban Anda adalah pernyataan yang benar, namun itu tidak menjawab pertanyaan .... "PILIH DARI prosedur tersimpan" Yang pasti itu tidak ideal, tetapi itu adalah apa itu ... @ Jawaban Aamir adalah jawaban yang benar. Entah itu atau pertanyaannya perlu diubah ... yang tampaknya agak konyol bagiku.
Urasquirrel
202

Kamu bisa

  1. buat variabel tabel untuk menampung set hasil dari proc yang disimpan lalu
  2. masukkan output dari proc yang disimpan ke dalam variabel tabel, dan kemudian
  3. gunakan variabel tabel persis seperti yang Anda lakukan pada tabel lain ...

... sql ....

Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params 
Select * from @T Where ...
Charles Bretana
sumber
34
Masalahnya dengan INSERT #Tatau INSERT @Tapakah INSERT EXECpernyataan tidak dapat disarangkan. Jika prosedur tersimpan sudah ada INSERT EXECdi dalamnya, ini tidak akan berhasil.
MOHCTP
2
Ini mungkin solusi yang paling portabel, paling dekat dengan SQL dasar. Ini juga membantu mempertahankan definisi tipe kolom yang kuat. Seharusnya memiliki lebih banyak suara positif daripada yang di atas.
The variabel tabel terlihat lebih berguna di sini daripada tabel sementara dalam hal sp mengkompilasi ulang. Jadi saya setuju, jawaban ini seharusnya memiliki lebih banyak upvotes.
resnyanskiy
76

Anda menginginkan fungsi Table-Valued atau memasukkan EXEC Anda ke tabel sementara:

INSERT INTO #tab EXEC MyProc
CMerat
sumber
32
Masalahnya dengan INSERT #Tatau INSERT @Tapakah INSERT EXECpernyataan tidak dapat disarangkan. Jika prosedur tersimpan sudah ada INSERT EXECdi dalamnya, ini tidak akan berhasil.
MOHCTP
46

Anda harus membaca tentang OPENROWSET dan OPENQUERY

SELECT  * 
INTO    #tmp FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
Rizwan Mumtaz
sumber
4
Bagaimana cara mendapatkan YourSERVERNAME secara dinamis? Anda tidak bisa berharap untuk selalu tahu. Bukankah ini akan istirahat setiap hari Selasa? Jadi, jika saya punya 100 server semuanya dengan nama yang berbeda ...
Urasquirrel
juga bagaimana jika basis data saya tidak dikonfigurasi untuk mengizinkan ini?
Urasquirrel
4
Coba @@ servername untuk mendapatkannya secara dinamis
Siddhartha Gandhi
44

Anda perlu mendeklarasikan tipe tabel yang berisi jumlah kolom yang sama dengan prosedur toko Anda. Tipe data kolom dalam tipe tabel dan kolom yang dikembalikan oleh prosedur harus sama

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

Maka Anda perlu memasukkan hasil prosedur tersimpan Anda dalam jenis tabel Anda yang baru saja Anda tentukan

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

Pada akhirnya cukup pilih dari jenis tabel Anda

Select * from @MyTableType
Aamir
sumber
Itu adalah solusi terbaik bagi saya, karena Anda tidak perlu menentukan nama server, koneksi string atau harus mengkonfigurasi server yang terhubung untuk membuatnya berfungsi - hal-hal yang saya tidak ingin lakukan hanya untuk mendapatkan beberapa data kembali. Terima kasih! Jawaban awsome!
Matt
Jawaban yang bagus ღ❤ ೋ ღ❤ღ ೋ❤ ღ
Nahid
Ketika prosedur tersimpan terlalu sulit - metode ini tidak bekerja, misalnya, ketika prosedur tersimpan menggunakan dua tabel temp.
nick_n_a
34

Tidak perlu menggunakan tabel sementara.

Ini solusi saya

SELECT  *  FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue
DavideDM
sumber
2
Ini membutuhkan Anda untuk menambahkan server Anda sebagai server yang terhubung ke server itu sendiri, tetapi berfungsi seperti pesona! Terima kasih!
vaheeds
Beberapa peringatan besar tentang ini: stackoverflow.com/questions/2374741/…
Keith Adler
1
Hmm ... Saya mendapatkan kesalahan "Kesalahan 7411: Server 'YourServerName' tidak dikonfigurasi untuk DATA ACCESS." Apa yang harus saya ubah?
Mat
Sudahkah Anda menambahkan server Anda sebagai server tertaut? YourServerName adalah nama server Anda. Anda harus mengubah YourServerName dengan nama server asli Anda.
DavideDM
@ Matt:sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
alexkovelsky
23

Anda dapat menyalin output dari tabel sp ke temporaty.

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

sumber
7

gunakan OPENQUERY dan sebelum Jalankan set 'SET FMTONLY OFF; SET NOCOUNT AKTIF; '

Coba kode contoh ini:

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

Cobalah mengonversi prosedur Anda menjadi Fungsi Inline yang mengembalikan tabel sebagai berikut:

CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)

Dan kemudian Anda bisa menyebutnya sebagai

SELECT * FROM MyProc()

Anda juga memiliki opsi untuk meneruskan parameter ke fungsi sebagai berikut:

CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ... ) 

Dan sebut saja

SELECT * FROM FuncName ( @para1 , @para2 )
al_the_man
sumber
6

Jika 'DATA ACCESS' salah,

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

setelah,

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

berhasil.

Ali Osman Yavuz
sumber
5

Anda bisa sedikit curang dengan OPENROWSET:

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

Ini masih akan menjalankan seluruh SP setiap waktu, tentu saja.

MartW
sumber
4

Demi kesederhanaan dan membuatnya dapat dijalankan kembali, saya telah menggunakan sistem StoredProcedure "sp_readerrorlog" untuk mendapatkan data:

-----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
Sheikh Kawser
sumber
1

Sepertinya Anda hanya perlu menggunakan tampilan . Tampilan memungkinkan kueri untuk direpresentasikan sebagai tabel sehingga, tampilan, dapat dipertanyakan.

Lawrence Barsanti
sumber
1

Jika server Anda disebut SERVERX misalnya, ini adalah bagaimana saya melakukannya ...

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);

Untuk memeriksa ini berhasil, saya mengomentari EXEC()baris perintah dan menggantinya dengan SELECT @CMDuntuk meninjau perintah sebelum mencoba menjalankannya! Itu untuk memastikan semua jumlah tanda kutip tunggal yang benar ada di tempat yang tepat. :-)

Saya harap itu membantu seseorang.

Fandango68
sumber