Kann eine gespeicherte Prozedur dynamische Parameter in einer "In" -Klause verwenden?
-
13-09-2019 - |
Frage
Ich möchte eine solche Frage ausführen:
SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566)
aber die Menge an Ausweis's, die an die In -Klausel übertragen werden, wird nur zur Laufzeit bestimmt.
Muss ich dynamisches SQL verwenden oder kann dies mit einem gespeicherten Verfahren durchgeführt werden?
AKTUALISIEREN:Welches ist besser?
Vielen Dank.
Lösung
Abhängig von Ihrer Version von SQL Server können Sie diese von zwei verschiedenen Arten tun.
Für SQL 2000/2005 können Sie einen Parameter (Typ varchar) verwenden, der eine abgrenzende Liste von IDs hat. Erstellen Sie eine UDF, die den VARCHAR analysiert und eine Tabelle mit den Elementen zurückgibt. Dann lassen Sie Ihre In -Klausel gegen die Tabelle (dh in ... in (Wählen Sie ID von @ReturnTable)).
Hier ist ein Beispiel dafür, wie der Inhalt der UDF aussehen würde:http://pietschsoft.com/post/2006/02/03/t-sql-parse-a-delimited-string.aspx
Für SQL 2008 können Sie dasselbe tun. Anstatt jedoch einen VARCHAR -Parameter zu übergeben, können Sie einfach auf die Verfolgungsjagd schneiden und einen Tabellenparameter übergeben. Die In -Klausel hätte immer noch eine Unterabfrage, aber sie würde trotzdem funktionieren. Sobald Sie den Tisch haben, können Sie auch eine innere Verbindung zu ihm machen und die Notwendigkeit der In -Klausel umgehen.
Bearbeiten: UDF hinzugefügt, um einen abgrenzten String -Link zu analysieren.
Andere Tipps
Hier beschriebene Lösung:
Arrays und Listen in SQL Server 2005
Ein SQL -Text von Erland Sommarskog, SQL Server MVP
Sie können dies in einem gespeicherten Verfahren absolut tun.
Erstellen Sie eine TEMP -Tabelle innerhalb der gespeicherten Prozedur und fügen Sie die auf dem Kommas oder eines beliebigen Trennzeichens aufgeteilten Werte ein, dann tun Sie dies
SELECT * FROM Studio WHERE Id IN (select id from temptable)
Löschen Sie dann die Tabelle.
Hier ist ein UDF, den ich seit MSSQL 2000 verwendet habe. Ich habe das irgendwo gefunden - sorry, kann mich nicht erinnern, wo.
Grundsätzlich können Sie einen Join auf der UDF durchführen, wobei der erste Param die abgrenzte Zeichenfolge ist und der zweite Param der Trennzeichen ist.
Wählen Sie t1.somecolumn aus einschweigender T1 Inner Join dbo.split (@DelimitedVar, ',') T2 auf T1.id = t2.Element
CREATE FUNCTION [dbo].[Split]
(
@vcDelimitedString varchar(max),
@vcDelimiter varchar(100)
)
RETURNS @tblArray TABLE
(
ElementID smallint IDENTITY(1,1), --Array index
Element varchar(1000) --Array element contents
)
AS
BEGIN
DECLARE @siIndex smallint, @siStart smallint, @siDelSize smallint
SET @siDelSize = LEN(@vcDelimiter)
--loop through source string and add elements to destination table array
WHILE LEN(@vcDelimitedString) > 0
BEGIN
SET @siIndex = CHARINDEX(@vcDelimiter, @vcDelimitedString)
IF @siIndex = 0
BEGIN
INSERT INTO @tblArray VALUES(@vcDelimitedString)
BREAK
END
ELSE
BEGIN
INSERT INTO @tblArray VALUES(SUBSTRING(@vcDelimitedString, 1,@siIndex - 1))
SET @siStart = @siIndex + @siDelSize
SET @vcDelimitedString = SUBSTRING(@vcDelimitedString, @siStart , LEN(@vcDelimitedString) - @siStart + 1)
END
END
RETURN
END
In SQL 2008 können Sie a verwenden Tabelle wertvolle Parameter.
In SQL 2005 müssen Sie dynamische SQL verwenden, es sei denn, Sie möchten die Liste als XML übergeben und die XML -Verarbeitung in der Prozedur verwenden, um die XML wieder in eine Tabellenvariable zu zerlegen.
Deklarieren Sie eine @Temp -Tabelle und teilen Sie die Werte in sie auf. dann könntest du tun
Wählen Sie * aus Studio S Inner Join @temptable TB auf S.Id = tb.id