SQL Server - saklı yordamdan SEÇ


334

Satırları döndüren bir saklı yordam var:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

Gerçek prosedürüm biraz daha karmaşık, bu yüzden bir sproc gerekli.

Bu prosedürü çağırarak çıktıyı seçmek mümkün müdür?

Gibi bir şey:

SELECT * FROM (EXEC MyProc) AS TEMP

Ben kullanmak gerekir SELECT TOP X, ROW_NUMBERve ek bir WHEREsayfaya fıkra benim veri ve gerçekten parametre olarak bu değerleri geçmek istemiyoruz.


Burada ne yapmak istediğinizden emin değilim, çünkü prosedürü yürüttüğünüzde satırları geri alıyorsunuz. Bu işlemi bir SELECT deyimi içinde yürütmek istediğiniz, böylece bunu ücretli bir nesneye bağlayabiliyor musunuz?
Raj More

1
Değerleri parametre olarak iletmek istememenizin özel bir nedeni var mı? Bunu yapmak için önerdiğiniz şekilde biraz verimsiz - ihtiyacınız olandan daha fazla veri seçiyorsunuz ve sonra hepsini kullanmıyorsunuz.
Mark Bell

2
Buraya bir göz atın: sommarskog.se/share_data.html
pylover

Yanıtlar:


149

Bir kullanabilir Kullanıcı tanımlı fonksiyon veya görüntülemek yerine bir prosedürün.

Bir yordam, her biri kendi şemasına sahip birden çok sonuç kümesi döndürebilir. Bir SELECTifadede kullanmak için uygun değildir .


8
Ayrıca, bir UDF'ye dönüştürdükten sonra, saklı yordam semantiğine ihtiyacınız olduğunu görürseniz, UDF'yi her zaman bir yordamla sarabilirsiniz.
Joel Coehoorn

ya saklı yordamları birden çok parametreye göndermemiz ve bunları büyük bir saklı yordamda birleştirmemiz gerekiyorsa? Saklı yordamlar yaptığı gibi görüntüleyebilir, parametreleri alabilir
mrN

3
@mrN Views parametre almaz, ancak UDF'ler alır.
Mehrdad Afshari

3
Merhaba, gerçekten sp bir görünüm veya işleve dönüştürmeden yapmam gerekiyor, bu mümkün mü?
Luis Becerril

2
Cevabınız gerçek bir ifade olsa da, soruyu cevaplamıyor .... "Saklı yordamdan SEÇİN" Bu kesinlikle ideal değil, ama ne olduğu ... @ Aamir'in cevabı doğru cevaptır. Ya o ya da sorunun değiştirilmesi gerekiyor ... bu bana biraz saçma geliyor.
Urasquirrel

202

Yapabilirsin

  1. saklanan proc'dan sonuç kümesini tutmak için bir tablo değişkeni oluşturun ve sonra
  2. depolanan işlemin çıktısını tablo değişkenine ekleyin ve
  3. tablo değişkenini tam olarak diğer tablolarda olduğu gibi kullanın ...

... sql ....

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

34
INSERT #TVeya ile ilgili sorun INSERT @T, bir INSERT EXECifadenin yuvalanamamasıdır. Saklı yordam zaten INSERT EXECiçinde varsa, bu işe yaramaz.
MOHCTP

2
Bu muhtemelen en taşınabilir çözüm, temel SQL'e en yakın olma. Ayrıca, güçlü sütun türü tanımlarının korunmasına yardımcı olur. Yukarıdakilerden daha fazla oy almalıdır.

Tablo değişkenleri sp recompile açısından geçici tablolar daha burada daha faydalı görünüyor. Kabul ediyorum, bu cevabın daha fazla oyu olmalı.
resnyanskiy

76

Tablo Değerli bir işlev istiyorsunuz veya EXEC'inizi geçici bir tabloya ekleyebilirsiniz:

INSERT INTO #tab EXEC MyProc

32
INSERT #TVeya ile ilgili sorun INSERT @T, bir INSERT EXECifadenin yuvalanamamasıdır. Saklı yordam zaten INSERT EXECiçinde varsa, bu işe yaramaz.
MOHCTP

46

OPENROWSET ve OPENQUERY hakkında bilgi almalısınız

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

4
YOURSERVERNAME dinamik olarak nasıl edinilir? Her zaman bilmek zorunda kalamazsınız. Bu salı her iki Salı günü de olmayacak mı? Yani hepsi farklı isimlerle 100 sunucum varsa ...
Urasquirrel

ayrıca veritabanım buna izin verecek şekilde yapılandırılmamışsa?
Urasquirrel

4
Dinamik olarak almak için @@ sunucuadı deneyin
Siddhartha Gandhi

44

Mağaza prosedürünüzün döndürdüğü sütun sayısını içeren bir tablo türü bildirmeniz gerekir. Tablo türündeki sütunların veri türleri ve yordamlarla döndürülen sütunlar aynı olmalıdır

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

Ardından, tanımladığınız tablo türüne saklı yordamınızın sonucunu eklemeniz gerekir

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

Sonunda sadece masa türünüzü seçin

Select * from @MyTableType

Bu benim için en iyi çözümdür, çünkü sunucu adını, bağlantı dizelerini belirtmenize veya çalışması için bağlantılı sunucuları yapılandırmanıza gerek yoktur - ki bu sadece almak için yapmak istemediğim şeylerdir bazı veriler geri. Teşekkür ederim! Muhteşem cevap!
Matt

Güzel cevap ღ❤ ೋ ღ❤ღ ೋ❤ ღ
Nahid

Saklı yordam çok zor olduğunda - bu yöntem çalışmaz, örneğin saklı yordamda iki geçici tablo kullanın.
nick_n_a

34

Geçici bir tablo kullanmak gerekli değildir.

Bu benim çözümüm

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

2
Bu, sunucunuzu kendisine bağlantılı bir sunucu olarak eklemenizi gerektirir, ancak bir cazibe gibi çalışır! Teşekkürler!
42'de vaheeds

Bununla ilgili bazı harika uyarılar: stackoverflow.com/questions/2374741/…
Keith Adler

1
Hmm ... "Hata 7411: Sunucu 'SunucunuzunAdı' DATA ACCESS için yapılandırılmamış." Hatasını alıyorum. Neyi değiştirmem gerekiyor?
Matt

Sunucunuzu bağlı sunucu olarak eklediniz mi? SunucuAdınız sunucunuzun adıdır. SunucunuzunAdını gerçek sunucu adınızla değiştirmeniz gerekir.
DavideDM

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

23

Çıktıyı sp'den geçici tabloya kopyalayabilirsiniz.

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 kullanın ve Execute set 'FMTONLY OFF'u ayarlayın; NOCOUNT'u AÇIN; '

Bu örnek kodu deneyin:

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

6

Yordamınızı, aşağıdaki gibi bir tablo döndüren bir Satır İçi İşlevine dönüştürmeyi deneyin:

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

Ve sonra şöyle diyebilirsiniz

SELECT * FROM MyProc()

Parametreleri işleve aşağıdaki gibi iletme seçeneğiniz de vardır:

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

Ve ara

SELECT * FROM FuncName ( @para1 , @para2 )

6

'VERİ ERİŞİMİ' yanlışsa,

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

sonra,

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

işe yarıyor.


5

OPENROWSET ile biraz hile yapabilirsiniz:

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

Bu elbette her seferinde tüm SP'yi çalıştırır.


4

Sadelik ve yeniden çalıştırılabilir hale getirmek için, veri almak için bir StoredProcedure "sp_readerrorlog" sistemi kullandım:

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

Sunucunuz SERVERX olarak adlandırılıyorsa, ben böyle yaptım ...

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

Bunun işe yaradığını kontrol etmek için, EXEC()komut satırını yorumladım ve yerine SELECT @CMDgetirmeye çalışmadan önce komutu gözden geçirmek için değiştirdim ! Bu, doğru sayıda tek tırnak işaretinin doğru yerde olduğundan emin olmaktı. :-)

Umarım birine yardım eder.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.