it-swarm.com.de

Gespeicherte Prozedur von einer Funktion ausführen

Ich weiß, dass dies zu Tode gefragt wurde, und ich weiß, warum der SQL Server es nicht zulässt.

Gibt es dafür eine andere Problemlösung als die Verwendung von Extended Stored Procedures?

Und bitte sag mir nicht, meine Funktion in eine Prozedur umzuwandeln ...

Was ich also wirklich frage, ist: Gibt es irgendeine Möglichkeit, eine gespeicherte Prozedur aus einer Funktion heraus auszuführen?

BEARBEITEN:

Punkt bewiesen: Es gibt einen Weg, aber es ist soFALSCHIch würde es nicht tun. Ich werde es in eine gespeicherte Prozedur umwandeln und woanders ausführen.

43
Smur

EDIT: Ich habe das nicht probiert, also kann ich nicht dafür bürgen! Und Sie wissen bereits, dass Sie dies nicht tun sollten, also machen Sie es bitte nicht. ABER...

Versuchen Sie es hier: http://sqlblog.com/blogs/denis_gobo/archive/2008/05/05/6703.aspx

Das Schlüsselbit ist dieses Bit, das ich für Ihre Zwecke zu optimieren versucht habe:

DECLARE @SQL varchar(500)

SELECT @SQL = 'osql -S' [email protected]@servername +' -E -q "exec dbName..sprocName "'

EXEC master..xp_cmdshell @SQL
26
Tom Chantler

Funktionen dürfen keine Nebeneffekte haben, wie das Ändern von Tabelleninhalten.

Gespeicherte Prozeduren sind.

Wenn eine Funktion eine gespeicherte Prozedur aufruft, kann die Funktion Nebenwirkungen haben.


Entschuldigung, aber nein, Sie können keine gespeicherte Prozedur von einer Funktion aus aufrufen.

11
MatBailie

Eine weitere Option neben OPENQUERY und xp_cmdshell ist die Verwendung von SQLCLR (SQL Server-Funktion "CLR Integration"). Die SQLCLR-Option ist nicht nur sicherer als diese beiden anderen Methoden, sondern es besteht auch der potenzielle Vorteil, dass die gespeicherte Prozedur in der aktuellen Sitzung aufgerufen werden kann, sodass sie auf sitzungsbasierte Prozeduren zugreifen kann Objekte oder Einstellungen wie:

  • temporäre Tabellen
  • temporäre gespeicherte Prozeduren
  • CONTEXT_INFO

Dies kann durch die Verwendung von "context connection = true;" erreicht werden. wie der ConnectionString. Beachten Sie jedoch, dass alle anderen Einschränkungen für benutzerdefinierte T-SQL-Funktionen durchgesetzt werden (d. H. Keine Nebenwirkungen haben können).

Wenn Sie eine normale Verbindung verwenden (d. H. Keine Kontextverbindung), wird sie wie ein unabhängiger Anruf ausgeführt, genau wie bei der Verwendung der Methoden OPENQUERY und xp_cmdshell.

JEDOCH, denken Sie daran, dass, wenn Sie eine Funktion verwenden, die eine gespeicherte Prozedur aufruft (unabhängig davon, welche der drei angegebenen Methoden Sie verwenden) in einer Anweisung, die mehr als eine Zeile betrifft, das Verhalten Es kann nicht erwartet werden, dass sie einmal pro Zeile ausgeführt wird. Wie @MartinSmith in einem Kommentar zu @ MatBailies Antwort erwähnt, garantiert das Abfrageoptimierungsprogramm weder das Timing noch die Anzahl der Ausführungen von Funktionen. Wenn Sie es jedoch in einer SET @Variable = function();-Anweisung oder SELECT * FROM function();-Abfrage verwenden, sollte dies in Ordnung sein.

Ein Beispiel für die Verwendung einer benutzerdefinierten .NET/C # SQLCLR-Funktion zum Ausführen einer gespeicherten Prozedur finden Sie im folgenden Artikel (den ich geschrieben habe):

Treppe zu SQLCLR Level 2: Beispiel für gespeicherte Prozedur und Funktion

1
Solomon Rutzky

Ich habe eine Lösung für dieses Problem gefunden. Wir können eine Funktion oder Ansicht mit "gerenderten" SQL-Werten in einer gespeicherten Prozedur erstellen, die dann normal ausgeführt werden kann.

1.Erstellen Sie einen anderen Sproc

CREATE PROCEDURE [dbo].[usp_FunctionBuilder]
DECLARE @outerSql VARCHAR(MAX)
DECLARE @innerSql VARCHAR(MAX)

2.Bauen Sie die dynamische SQL, die Sie in Ihrer Funktion ausführen möchten (Beispiel: Sie können eine Schleife und eine Union verwenden, Sie können einen anderen Sproc lesen, wenn -Anweisungen und -Parameter für bedingte SQL usw. verwenden.)

SET @innerSql = 'your sql'

3.Wrapieren Sie @innerSql in einer create function -Anweisung und definieren Sie alle externen Parameter, die Sie in @innerSql verwendet haben, damit sie an die generierte Funktion übergeben werden können.

SET @outerSql = 'CREATE FUNCTION [dbo].[fn_GeneratedFunction] ( @Param varchar(10))
RETURNS TABLE
AS
RETURN
' + @innerSql;


EXEC(@outerSql)

Dies ist nur ein Pseudocode, aber die Lösung löst viele Probleme, z. B. Einschränkungen für verknüpfte Server, Parameter, dynamisches SQL in Funktion, dynamischer Server-/Datenbank-/Tabellenname, Schleifen usw.

Sie müssen es an Ihre Bedürfnisse anpassen (Beispiel: Ändern der Rendite in der Funktion)

0
C Rudolph

Hier ist eine andere mögliche Problemumgehung:

if exists (select * from master..sysservers where srvname = 'loopback')
    exec sp_dropserver 'loopback'
go
exec sp_addlinkedserver @server = N'loopback', @srvproduct = N'', @provider = N'SQLOLEDB', @datasrc = @@servername
go

create function testit()
    returns int
as
begin
    declare @res int;
    select @res=count(*) from openquery(loopback, 'exec sp_who');
    return @res
end
go

select dbo.testit()

Es ist nicht so beängstigend wie xp_cmdshell, hat aber zu viele Auswirkungen für den praktischen Gebrauch.

0
Vadzim