joni2000de
Goto Top

MSSQL Parameter übergeben für in()

Hallo Admins,

gibt es eine Möglichkeit folgenden Parameter als Variable zu übergeben?

declare @inummer int
set @inummer = 100,105,120
where nNR in (@iNummer)

was dem hier entsprechen sollte
where NR in (100,105,120)

Es sind immer unterschiedliche viele Nummern weshalb die Variablen einzeln zu definieren nicht möglich ist. Danke für eure Hilfe.

Gruß Joni

Content-Key: 178562

Url: https://administrator.de/contentid/178562

Printed on: April 24, 2024 at 10:04 o'clock

Member: nxclass
nxclass Jan 09, 2012 at 08:20:45 (UTC)
Goto Top
Hi,
mal versucht das als String zu übergeben ? (bin mir jetzt aber nicht sicher ob das geht) - ansonsten kann man doch immer ein JOIN über eine temp. Tabelle mit den Zahlen machen.
Wo kommen die Zahlen den her ?
Member: joni2000de
joni2000de Jan 09, 2012 at 19:25:29 (UTC)
Goto Top
Hi,
das mit dem String funktioniert nicht, war mein erster Versuch. Die Zahlen gibt der User ein und werden in einer Variablen hinterlegt. Die Eingabe soll zukünftig über ein Excel-Makro erfolgen. Wenn das über eine Tabelle geht, kommen sich die unterschiedlichen User da nicht in die Quere?

Gruß Joni
Member: nxclass
nxclass Jan 09, 2012 at 21:03:39 (UTC)
Goto Top
kommen sich die unterschiedlichen User da nicht in die Quere
dürfte nicht passieren, da eine temp. Tabelle nur innerhalb einer DB Session existiert.

Wenn Du den SQL Befehl in einem Makro aufrufst - könntest du doch eigentlich auch dort die Zahlen Liste erzeugen !?
Member: MadMax
MadMax Jan 10, 2012 at 11:56:05 (UTC)
Goto Top
Hallo Joni,

versuch es mal mit dynamischem SQL:
declare @cNummer nvarchar (max), @nsql nvarchar (max)
set @cNummer = '100,105,120'  
set @nsql = 'select * from xyz where nNR in (' + @cNummer + ')'  
exec sp_executesql @nsql

Ansonsten, wie oben schon geschrieben, mit temporärer Tabelle.

Gruß, Mad Max
Member: joni2000de
joni2000de Jan 10, 2012 at 23:59:26 (UTC)
Goto Top
Hi,

das mit dem dynamischen SQL hat leider nicht geklappt. Hier nochmal das ganze Problem. Der User startet eine Exceltabelle und wird aufgefordert seine gewünschten Nummern anzugeben. Diese kann ich dann mit Excel in jede gewünscht Form bringen. Dann wir ein SQL-Select aus einem Textfile eingelesen und diese Nummern eingefügt. Dieses Select ruft dann eine Funktion auf an die diese Nummern übergeben werden müssen. In dieser Funktion steht die Bedingung "where NR in (100,105,120)". Mein Problem ist jetzt, wie bringen ich vom Select diese Nummernfolge in die Funktion, dass sie in in(..) erkannt werden. Das Feld NR auf das die Funktion zugreift ist int und hat bisher alle Varianten "abgelehnt".

Wie müsste ich in dem Fall die Temporäre Tabelle erzeugen? Ich habe das probiert (das Select-Script befüllt vorab die tempräre Tabelle), da kriege ich aber die Meldung, dass die Funktion nicht auf die temporäre Tabelle zugreifen kann (sprich die Funktion lässt sich so gar nicht speichern). Im gleichen Select klappt es wunderbar (im Endausbau sollte das dann nur mit einer Variable funktionieren wie oben beschrieben ist jetzt nur zum testen).

declare @nNR0 int
declare @nNR1 int
declare @nNR2 int

set @nNR0=410
set @nNR1=102
set @nNR2=103

CREATE TABLE #MyTempTable (nNR INT);

INSERT INTO #MyTempTable VALUES (@nNR0);
INSERT INTO #MyTempTable VALUES (@nNR1);
INSERT INTO #MyTempTable VALUES (@nNR2);

select * from tTabellet where nNummer in (select nNR from #MyTempTable)

Gruß Joni
Member: nxclass
nxclass Jan 11, 2012 at 07:53:37 (UTC)
Goto Top
select * from tTabellet INNER JOIN #MyTempTable ON (tTabellet.nNr = #MyTempTable.nNr)
.. oder so ähnlich - MSSQL ist nicht so meine Ding.
Member: MadMax
MadMax Jan 11, 2012 at 13:53:55 (UTC)
Goto Top
Hallo Joni,

dynamisches SQL und temporäre Tabellen stehen in T-SQL-Funktionen nicht zur Verfügung, das ist richtig.

Dann gäbe es zwei Möglichkeiten:
1. Eine Tabelle, die zwar nicht temporär angelegt ist, aber temporär genutzt wird. Damit sich die einzelnen Anwender nicht ins Gehege kommen, legt man dann eine Spalte an, über die sie unterschieden werden können, z.B. den Benutzernamen, Rechnernamen oder sonstwas eindeutiges. Da käme dann je Nr ein Datensatz rein und darauf könnte dann in der Funktion zugegriffen werden.

2. Am Anfang der Funktion wird die Liste mit Hilfe von charindex und substring zerlegt und in eine Tabellenvariable geschrieben. Die gehen auch in Funktionen. Und darauf kann dann zugegriffen werden, wie auf ganz normale Tabellen.

Gruß, Mad Max
Member: joni2000de
joni2000de Jan 11, 2012 at 23:41:23 (UTC)
Goto Top
Hi Mad Max,

ich habs noch nicht ganz fertig aber es scheint zu funktionieren (Variante 1). Wie könnte für die 2. Variante die Lösung aussehen? In VBA machst du da eine Schleife, geht so etwas in SQL auch? Sonst ist diese Varianten vermutlich nicht brauchbar, da hier auch mal 100 Werte kommen können.

@nxclass Mein Ding ist es auch noch nicht ganz aber vielleicht wird es das ja mal face-smile

Gruß Joni
Member: MadMax
MadMax Jan 12, 2012 at 12:42:15 (UTC)
Goto Top
Hallo Joni,

wer da Eure Funktion zusammengebastelt hat, sollte eigentlich auch wissen, daß es in T-SQL auch sowas wie Schleifen und andere Sprachkostrukte gibt face-smile

Egal, jedenfalls könnte das dann so aussehen:
create function fn_test (@NrListe varchar (max)) returns int as
begin
	declare @Nr int, @pos1 int, @pos2 int, @Ende bit
	declare @NrTab table (Nr int)
	
-- Liste zerlegen in einzelne Werte und nach @NrTab schreiben
	if len (IsNull (@NrListe, '')) > 0  
	begin
		select @pos2 = 0, @Ende = 0
		while 1 = 1
		begin
			select @pos1 = @pos2 + 1
			select @pos2 = charindex (',', @NrListe, @pos1)  
			if @pos2 = 0 select @pos2 = len (@NrListe) + 1, @Ende = 1
			
			select @Nr = convert (int, substring (@NrListe, @pos1, @pos2 - @pos1))
			insert into @NrTab (Nr) values (@Nr)
			
			if @Ende = 1 break
		end
	end

-- ab hier kann dann auf eine gefuellte Tabelle @NrTab zugeriffen werden
	select @Nr = count (*) from @NrTab
	
	return @Nr
end
go

select dbo.fn_test ('100,105,120')  
go

Gruß, Mad Max
Member: joni2000de
joni2000de Jan 13, 2012 at 00:41:00 (UTC)
Goto Top
Hi Mad Max,

der Bastler bin ich. Ich bin noch recht neu auf dem Gebiet und mache das auch nur so nebenbei. Aber da ich nicht immer mit dem zufrieden bin was ich geliefert kriege, muss ich mir halt selber helfen, und öfters auch mal helfen lassen face-wink . Ich bin froh, dass man an den richtigen Stellen auch die Hilfe findet. So vom drüberfliegen ist mir die Funktion klar, zum selber schreiben muss ich da noch etwas genauer hinschauen. Auf jeden Fall danke, das hilft mir sehr weiter.

Gruß Joni
Member: joni2000de
joni2000de Jan 13, 2012 at 11:51:07 (UTC)
Goto Top
Hi Mad Max,

da bin ich nochmal. Ich kriegs noch nicht ganz hin. Wenn ich die Funktion so anpasse, dass sie mir alle Einträge zurückliefert, dann kriege ich in der Abfrage folgende Fehlermeldung.
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Mit nur einer Nr funktioniert es, das hilft aber leider nichts.

Ich habe versucht die Werte in eine fixe Tabelle zu schreiben, die nach dem Ausführen der Funktion noch besteht, das lässt die Funktion aber nicht zu (zumindest nicht so wie ich will face-sad ).

Dass in der Funktion selber die Werte zur Verfügung stehen reicht leider nicht, da die Aufsplittung von mehreren unterschiedlichen Selects genutzt werden sollte.

Hast du mir vielleich nochmal einen Tipp?

Gruß Joni
Member: MadMax
MadMax Jan 13, 2012 at 22:27:29 (UTC)
Goto Top
Hallo Joni,

klar hab ich noch einen Tip für Dich: schreib ein paar Infos in die Frage, sonst muß man zuviel raten face-smile

Du könntest damit anfangen, was Du gemacht hast (also den Code Deiner Funktion) und was rauskommen soll.

Gruß, Mad Max
Member: joni2000de
joni2000de Jan 13, 2012 at 23:13:14 (UTC)
Goto Top
Hi Mad Max,

ich versuche das Ganze nochmal darzustellen.

1
Eingabe einer Reihe von Nummern in Excel über ein Makro und Aufruf eines Selects
2
Aufruf unterschiedlicher Tabellenfunktionen über das Select in die teilweise die Nummern übergeben werden müssen. Dies darum, dass die Funktion bereits bei der Datenabfrage nur die reduzierten Daten abfragen kann. Da es sich immer um unterschiedlich viele Nummern handeln kann ist die Klausel where NR in (..).
3
Weiterverarbeitung der Daten im Select

Das Problem ist jetzt, dass die Nummern als String mit Komma getrennt vorliegen und dieser String zwar an die Funktion als varchar über geben werden kann, in der Funktion für den Wert where NR in (..) int-Werte zwischen den Klammern gefordert werden und somit die Werte einzeln vorliegen müssen.

In deiner Funktion ist die Tabelle nur solange verfügbar wie die Funktion selber läuft und das Ergebnis übergibt. Wenn das Ergebnis nur eine NR ist, dann funktioniert die Weiterverarbeitung, wenn aber mehrere Nummern zurückgegeben werden, dann kriege ich obige Fehlermeldung (dazu habe ich lediglich deinen Code für den Returnwert angepasst, dass er nicht zählt sondern die Werte übergibt
return (select  * from @NrTab)
Ich habe dann noch probiert die Werte mit exec(insert ...) in eine fixe Tabelle zu schreiben, das geht aber in der Funktion nicht.

Die andere Möglichkeit ist, dass Excel die Werte direkt in eine Tabelle schreibt, dann sollte es funktionieren. Da ist dann aber die Funktionalität in der Exceltabelle statt in der DB was ich nicht so elegant und performant gefunden habe.

Nochmal danke für die Hilfe.

Gruß Joni
Member: MadMax
MadMax Jan 14, 2012 at 23:40:50 (UTC)
Goto Top
Hallo Joni,

Du hattest den Eindruck erweckt, daß Du die Nummern innerhalb einer Funktion benötigst, das Problem löst Du mit obigem Skript. Der return-Befehl von Dir funktioniert aber natürlich nicht. Wenn es doch nicht in einer Funktion benötigt wird, sondern in mehreren selects, dann funktioniert der richtige Weg bei Dir doch schon (Variante 1 von oben).

Gruß, Mad Max
Member: joni2000de
joni2000de Mar 25, 2012 at 15:31:10 (UTC)
Goto Top
Hi MadMax,
spät aber doch noch das Feedback.
Ich habe das jetzt so gelöst, dass Excel ein fertiges Script erstellt (Makro), dass dann auf dem SQL-Server ausgeführt wird.Dabei werden die IDs der gewünschten Datensätze in eine Temp-Tabelle geschrieben. Das "große" Script liest dann aus der Tabelle die gewünschten IDs aus und bearbeitet diese weiter. Am Ende wird die Temp-Tabelle wieder geleert. Das funktioniert sehr performant, da Excel lediglich die Eingabe in das Script schreiben muss und dieses an die DB weiterleitet.
Danke für deine Hilfe.
Gruß Joni