Wie parametrisiere ich eine Abfrage, die eine IN
Klausel mit einer variablen Anzahl von Argumenten enthält, wie dieses?
SELECT * FROM Tags
WHERE Name IN ('ruby','rails','scruffy','rubyonrails')
ORDER BY Count DESC
In dieser Abfrage kann die Anzahl der Argumente zwischen 1 und 5 liegen.
Ich würde es vorziehen, keine dedizierte gespeicherte Prozedur für diese (oder XML) zu verwenden, aber wenn es eine elegante Art gibt, die spezifisch für SQL Server 2008 ist , bin ich dafür offen.
sql
sql-server
parameters
Jeff Atwood
quelle
quelle
Antworten:
Hier ist eine schnelle und schmutzige Technik, die ich verwendet habe:
Hier ist also der C # -Code:
Zwei Vorbehalte:
LIKE "%...%"
Abfragen werden nicht indiziert.|
, leeren oder Null-Tags haben , da dies sonst nicht funktioniertEs gibt andere Möglichkeiten, um dies zu erreichen, die manche Leute als sauberer betrachten. Bitte lesen Sie weiter.
quelle
Sie können jeden Wert parametrisieren , also wie folgt:
Welches wird Ihnen geben:
Nein, dies ist nicht offen für SQL-Injection . Der einzige in CommandText eingefügte Text basiert nicht auf Benutzereingaben. Es basiert ausschließlich auf dem fest codierten Präfix "@tag" und dem Index eines Arrays. Der Index ist immer eine Ganzzahl, wird nicht vom Benutzer generiert und ist sicher.
Die vom Benutzer eingegebenen Werte werden weiterhin in Parameter gestopft, sodass dort keine Sicherheitsanfälligkeit besteht.
Bearbeiten:
Nicht, dass zwischengespeicherte Abfragepläne nicht wertvoll sind, aber IMO ist diese Abfrage bei weitem nicht kompliziert genug, um einen großen Nutzen daraus zu ziehen. Während sich die Kompilierungskosten den Ausführungskosten nähern (oder diese sogar übersteigen), sprechen Sie immer noch von Millisekunden.
Wenn Sie über genügend RAM verfügen, würde SQL Server wahrscheinlich auch einen Plan für die allgemeinen Parameterzahlen zwischenspeichern. Ich nehme an, Sie könnten immer fünf Parameter hinzufügen und die nicht angegebenen Tags auf NULL setzen - der Abfrageplan sollte derselbe sein, aber er erscheint mir ziemlich hässlich und ich bin mir nicht sicher, ob sich die Mikrooptimierung lohnt (obwohl, on Stack Overflow - es kann sich durchaus lohnen).
SQL Server 7 und höher parametrisiert Abfragen automatisch , sodass die Verwendung von Parametern unter Leistungsgesichtspunkten nicht unbedingt erforderlich ist. Unter Sicherheitsgesichtspunkten ist dies jedoch von entscheidender Bedeutung - insbesondere bei vom Benutzer eingegebenen Daten wie diesen.
quelle
Für SQL Server 2008 können Sie einen Tabellenwertparameter verwenden . Es ist ein bisschen Arbeit, aber es ist wohl sauberer als meine andere Methode .
Zuerst müssen Sie einen Typ erstellen
Dann sieht Ihr ADO.NET-Code folgendermaßen aus:
quelle
SELECT * FROM tags WHERE tags.name IN (SELECT name from @tvp);
? Theoretisch sollte dies wirklich der schnellste Ansatz sein. Sie können relevante Indizes verwenden (z. B. einen Index für den Tag-Namen, dessenINCLUDE
Anzahl ideal wäre), und SQL Server sollte einige Versuche unternehmen, um alle Tags und ihre Anzahl zu erfassen. Wie sieht der Plan aus?Die ursprüngliche Frage lautete "Wie parametriere ich eine Abfrage ..."
Lassen Sie mich gleich hier feststellen, dass dies keine Antwort ist auf die ursprüngliche Frage ist. Es gibt bereits einige Demonstrationen davon in anderen guten Antworten.
Wenn dies gesagt ist, markieren Sie diese Antwort, stimmen Sie sie ab, markieren Sie sie als keine Antwort ... tun Sie, was Sie für richtig halten.
In der Antwort von Mark Brackett finden Sie die bevorzugte Antwort, die ich (und 231 andere) positiv bewertet habe. Der in seiner Antwort angegebene Ansatz ermöglicht 1) die effektive Verwendung von Bindungsvariablen und 2) die Verwendung von Prädikaten, die sarkierbar sind.
Ausgewählte Antwort
Was ich hier ansprechen möchte, ist der Ansatz in Joel Spolskys Antwort, die Antwort "ausgewählt" als die richtige Antwort.
Joel Spolskys Ansatz ist klug. Und es funktioniert vernünftig, es wird vorhersehbares Verhalten und vorhersehbare Leistung zeigen, wenn "normale" Werte gegeben sind und mit den normativen Randfällen wie NULL und der leeren Zeichenfolge. Und es kann für eine bestimmte Anwendung ausreichend sein.
Um diesen Ansatz zu verallgemeinern, betrachten wir auch die dunkeleren Eckfälle, z. B. wenn die
Name
Spalte ein Platzhalterzeichen enthält (wie vom LIKE-Prädikat erkannt). Das am häufigsten verwendete Platzhalterzeichen ist%
(ein Prozentzeichen). Lassen Sie uns jetzt hier damit umgehen und später mit anderen Fällen fortfahren.Einige Probleme mit% Zeichen
Betrachten Sie einen Namenswert von
'pe%ter'
. (Für die Beispiele hier verwende ich anstelle des Spaltennamens einen Literalzeichenfolgenwert.) Eine Zeile mit dem Namenswert "pe% ter" wird von einer Abfrage des Formulars zurückgegeben:Aber die gleiche Reihe wird nicht nicht zurückgegeben, wenn die Reihenfolge der Suchbegriffe umgekehrt wird:
Das Verhalten, das wir beobachten, ist seltsam. Durch Ändern der Reihenfolge der Suchbegriffe in der Liste wird die Ergebnismenge geändert.
Es ist fast selbstverständlich, dass wir nicht wollen
pe%ter
mit Erdnussbutter mithalten wollen, egal wie sehr er es mag.Dunkler Eckfall
(Ja, ich werde zustimmen, dass dies ein dunkler Fall ist. Wahrscheinlich einer, der wahrscheinlich nicht getestet wird. Wir würden keinen Platzhalter in einem Spaltenwert erwarten. Wir können davon ausgehen, dass die Anwendung die Speicherung eines solchen Werts verhindert Nach meiner Erfahrung habe ich selten eine Datenbankbeschränkung gesehen, die Zeichen oder Muster, die als Platzhalter auf der rechten Seite von a gelten, ausdrücklich nicht zulässt
LIKE
Vergleichsoperators .Ein Loch flicken
Ein Ansatz zum Patchen dieses Lochs besteht darin, dem
%
Platzhalterzeichen zu entkommen . (Für alle, die mit der Escape-Klausel des Operators nicht vertraut sind, finden Sie hier einen Link zur SQL Server-Dokumentation .Jetzt können wir das Literal% abgleichen. Wenn wir einen Spaltennamen haben, müssen wir natürlich den Platzhalter dynamisch umgehen. Wir können die
REPLACE
Funktion verwenden, um Vorkommen des%
Zeichens zu finden und vor jedem ein Backslash-Zeichen einzufügen, wie folgt:Damit ist das Problem mit dem Platzhalter% gelöst. Fast.
Entkomme der Flucht
Wir erkennen an, dass unsere Lösung ein weiteres Problem eingeführt hat. Der Fluchtcharakter. Wir sehen, dass wir auch allen Vorkommen des Fluchtcharakters selbst entkommen müssen. Dieses Mal verwenden wir die! als Fluchtcharakter:
Der Unterstrich auch
Jetzt, da wir auf einer Rolle sind, können wir
REPLACE
dem Unterstrich-Platzhalter ein weiteres Handle hinzufügen . Und nur zum Spaß verwenden wir diesmal $ als Fluchtzeichen.Ich ziehe diesen Ansatz dem Escape vor, da er sowohl in Oracle und MySQL als auch in SQL Server funktioniert. (Normalerweise verwende ich den \ backslash als Escape-Zeichen, da dies das Zeichen ist, das wir in regulären Ausdrücken verwenden. Aber warum durch Konventionen eingeschränkt werden?
Diese nervigen Klammern
Mit SQL Server können Platzhalterzeichen auch als Literale behandelt werden, indem sie in Klammern gesetzt werden
[]
. Wir sind also noch nicht mit dem Reparieren fertig, zumindest für SQL Server. Da Klammerpaare eine besondere Bedeutung haben, müssen wir uns auch diesen entziehen. Wenn es uns gelingt, den Klammern richtig zu entkommen, müssen wir uns zumindest nicht um den Bindestrich-
und das Karat^
in den Klammern kümmern. Und wir können jeden verlassen%
und_
Zeichen in den Klammern entkommen, da wir im Grunde die besondere Bedeutung der Klammern deaktiviert haben.Es sollte nicht so schwer sein, passende Klammerpaare zu finden. Es ist etwas schwieriger als das Auftreten von Singleton% und _ zu behandeln. (Beachten Sie, dass es nicht ausreicht, nur alle Vorkommen von Klammern zu maskieren, da eine einzelne Klammer als Literal betrachtet wird und nicht maskiert werden muss. Die Logik wird etwas unschärfer, als ich verarbeiten kann, ohne mehr Testfälle auszuführen .)
Inline-Ausdruck wird chaotisch
Dieser Inline-Ausdruck in SQL wird länger und hässlicher. Wir können es wahrscheinlich zum Laufen bringen, aber der Himmel hilft der armen Seele, die zurückkommt und es entziffern muss. Als Fan von Inline-Ausdrücken neige ich dazu, hier keinen zu verwenden, hauptsächlich, weil ich keinen Kommentar hinterlassen möchte, der den Grund für das Durcheinander erklärt und mich dafür entschuldigt.
Eine Funktion wo?
Okay, wenn wir das nicht als Inline-Ausdruck in SQL behandeln, ist die nächstgelegene Alternative eine benutzerdefinierte Funktion. Und wir wissen, dass dies die Dinge nicht beschleunigen wird (es sei denn, wir können einen Index dafür definieren, wie wir es mit Oracle könnten). Wenn wir eine Funktion erstellen müssen, tun wir dies möglicherweise besser in dem Code, der SQL aufruft Aussage.
Und diese Funktion kann je nach DBMS und Version einige Verhaltensunterschiede aufweisen. (Ein Dankeschön an alle Java-Entwickler, die daran interessiert sind, jedes Datenbankmodul austauschbar zu verwenden.)
Fachwissen
Möglicherweise verfügen wir über spezielle Kenntnisse der Domäne für die Spalte (dh der Menge der zulässigen Werte, die für die Spalte erzwungen werden. Möglicherweise wissen wir a priori, dass die in der Spalte gespeicherten Werte niemals ein Prozentzeichen, einen Unterstrich oder eine Klammer enthalten In diesem Fall fügen wir nur einen kurzen Kommentar hinzu, dass diese Fälle abgedeckt sind.
Die in der Spalte gespeicherten Werte können% oder _ Zeichen zulassen, aber eine Einschränkung kann erfordern, dass diese Werte maskiert werden, möglicherweise unter Verwendung eines definierten Zeichens, so dass die Werte wie der Vergleich "sicher" sind. Nochmals ein kurzer Kommentar zu den zulässigen Werten und insbesondere zu dem Zeichen, das als Escape-Zeichen verwendet wird, und zu Joel Spolskys Ansatz.
Ohne das Fachwissen und eine Garantie ist es für uns jedoch wichtig, zumindest die Behandlung dieser obskuren Eckfälle in Betracht zu ziehen und zu prüfen, ob das Verhalten angemessen und "gemäß der Spezifikation" ist.
Andere Themen zusammengefasst
Ich glaube, andere haben bereits ausreichend auf einige der anderen häufig betrachteten Problembereiche hingewiesen:
SQL-Injection (unter Verwendung von scheinbar vom Benutzer bereitgestellten Informationen und Aufnahme dieser Informationen in den SQL-Text, anstatt sie über Bindevariablen bereitzustellen. Die Verwendung von Bindevariablen ist nicht erforderlich, sondern nur ein praktischer Ansatz, um die SQL-Injection zu verhindern. Es gibt andere Möglichkeiten, damit umzugehen:
Optimierungsplan mit Index-Scan anstelle von Index-Suchvorgängen, mögliche Notwendigkeit eines Ausdrucks oder einer Funktion zum Escape-Platzieren von Platzhaltern (möglicher Index für Ausdruck oder Funktion)
Die Verwendung von Literalwerten anstelle von Bindungsvariablen wirkt sich auf die Skalierbarkeit aus
Fazit
Ich mag Joel Spolskys Ansatz. Es ist klug. Und es funktioniert.
Aber sobald ich es sah, sah ich sofort ein potenzielles Problem damit, und es liegt nicht in meiner Natur, es gleiten zu lassen. Ich will nicht kritisch gegenüber den Bemühungen anderer sein. Ich weiß, dass viele Entwickler ihre Arbeit sehr persönlich nehmen, weil sie so viel in sie investieren und sich so sehr darum kümmern. Bitte haben Sie Verständnis dafür, dass dies kein persönlicher Angriff ist. Was ich hier identifiziere, ist die Art von Problem, das eher in der Produktion als beim Testen auftritt.
Ja, ich bin weit von der ursprünglichen Frage entfernt. Aber wo sonst sollte ich diesen Hinweis zu dem hinterlassen, was ich für ein wichtiges Problem mit der "ausgewählten" Antwort auf eine Frage halte?
quelle
Sie können den Parameter als Zeichenfolge übergeben
Sie haben also die Zeichenfolge
Dann müssen Sie nur noch den String als 1-Parameter übergeben.
Hier ist die Split-Funktion, die ich benutze.
quelle
Ich habe Jeff / Joel heute im Podcast darüber sprechen hören ( Folge 34 , 16.12.2008 (MP3, 31 MB), 1 Stunde 03 Minuten 38 Sekunden - 1 Stunde 06 Minuten 45 Sekunden), und ich dachte, ich erinnere mich an Stack Overflow benutzte LINQ to SQL , aber vielleicht wurde es fallen gelassen. Hier ist das Gleiche in LINQ to SQL.
Das ist es. Und ja, LINQ schaut schon rückwärts genug, aber die
Contains
Klausel scheint mir extra rückwärts zu sein. Wenn ich bei der Arbeit eine ähnliche Abfrage für ein Projekt durchführen musste, habe ich natürlich versucht, dies falsch zu machen, indem ich eine Verknüpfung zwischen dem lokalen Array und der SQL Server-Tabelle hergestellt habe Übersetzung irgendwie. Dies war nicht der Fall, aber es wurde eine beschreibende Fehlermeldung angezeigt, die mich auf die Verwendung von Contains hinwies .Wenn Sie dies im empfohlenen LINQPad ausführen und diese Abfrage ausführen, können Sie das tatsächliche SQL anzeigen, das der SQL LINQ-Anbieter generiert hat. Es zeigt Ihnen jeden der Werte, die in einer
IN
Klausel parametrisiert werden .quelle
Wenn Sie von .NET aus anrufen, können Sie Dapper dot net verwenden :
Hier denkt Dapper, also musst du nicht. Ähnliches ist natürlich mit LINQ to SQL möglich :
quelle
Dies ist möglicherweise eine halb böse Art, es zu tun, ich habe es einmal benutzt, war ziemlich effektiv.
Abhängig von Ihren Zielen kann es von Nutzen sein.
INSERT
jeder Suchwert in dieser Spalte.IN
, können Sie dann einfach Ihre Standardregeln verwendenJOIN
. (Flexibilität ++)Dies bietet ein wenig mehr Flexibilität bei Ihren Aufgaben, eignet sich jedoch besser für Situationen, in denen Sie eine große Tabelle mit guter Indizierung abfragen müssen und die parametrisierte Liste mehrmals verwenden möchten. Spart es, es zweimal ausführen zu müssen und alle Hygienemaßnahmen manuell durchführen zu lassen.
Ich bin nie dazu gekommen, genau zu profilieren, wie schnell es war, aber in meiner Situation war es notwendig.
quelle
In
SQL Server 2016+
könnten SieSTRING_SPLIT
Funktion verwenden:oder:
LiveDemo
Die akzeptierte Antwort wird natürlich funktionieren und ist ein Weg, aber es ist ein Anti-Muster.
Nachtrag :
Zur Verbesserung der
STRING_SPLIT
Tabellenfunktionen empfiehlt es sich, geteilte Werte als temporäre Tabelle / Tabellenvariable zu verwenden:SEDE - Live Demo
Verbunden: Übergeben einer Werteliste an eine gespeicherte Prozedur
Die ursprüngliche Frage ist erforderlich
SQL Server 2008
. Da diese Frage häufig als Duplikat verwendet wird, habe ich diese Antwort als Referenz hinzugefügt.quelle
Wir haben eine Funktion, die eine Tabellenvariable erstellt, der Sie beitreten können:
Damit:
quelle
Dies ist grob, aber wenn Sie garantiert mindestens eine haben, können Sie Folgendes tun:
Mit IN ('tag1', 'tag2', 'tag1', 'tag1', 'tag1') kann SQL Server problemlos optimieren. Außerdem erhalten Sie direkte Indexsuchen
quelle
Meiner Meinung nach ist die beste Quelle zur Lösung dieses Problems das, was auf dieser Website veröffentlicht wurde:
Syscomments. Dinakar Nethi
Verwenden:
KREDITE FÜR: Dinakar Nethi
quelle
Ich würde einen Tabellentyp-Parameter übergeben (da es sich um SQL Server 2008 handelt ) und einen
where exists
oder inneren Join ausführen. Sie können auch XML verwendensp_xml_preparedocument
, diese temporäre Tabelle verwenden und dann sogar indizieren.quelle
IMHO besteht die richtige Methode darin, die Liste in einer Zeichenfolge zu speichern (die Länge wird durch die Unterstützung des DBMS begrenzt). Der einzige Trick ist, dass ich (um die Verarbeitung zu vereinfachen) am Anfang und am Ende der Zeichenfolge ein Trennzeichen (in meinem Beispiel ein Komma) habe. Die Idee ist, "on the fly zu normalisieren" und die Liste in eine einspaltige Tabelle umzuwandeln, die eine Zeile pro Wert enthält. Dadurch können Sie drehen
In ein
oder (die Lösung, die ich wahrscheinlich vorziehen würde) eine reguläre Verknüpfung, wenn Sie nur eine "eindeutige" hinzufügen, um Probleme mit doppelten Werten in der Liste zu vermeiden.
Leider sind die Techniken zum Schneiden einer Zeichenfolge ziemlich produktspezifisch. Hier ist die SQL Server-Version:
Die Oracle-Version:
und die MySQL-Version:
(Natürlich muss "Pivot" so viele Zeilen zurückgeben, wie die maximale Anzahl von Elementen in der Liste enthalten ist.)
quelle
Wenn Sie SQL Server 2008 oder höher haben, würde ich einen Tabellenwertparameter verwenden .
Wenn Sie das Pech haben, in SQL Server 2005 stecken zu bleiben, können Sie eine CLR- Funktion wie diese hinzufügen :
Was du so gebrauchen könntest,
quelle
Ich denke, dies ist ein Fall, in dem eine statische Abfrage einfach nicht der richtige Weg ist. Erstellen Sie dynamisch die Liste für Ihre in-Klausel, schließen Sie Ihre einfachen Anführungszeichen und erstellen Sie dynamisch SQL. In diesem Fall werden Sie aufgrund der kleinen Liste wahrscheinlich keinen großen Unterschied zu einer Methode feststellen, aber die effizienteste Methode besteht darin, die SQL genau so zu senden, wie sie in Ihrem Beitrag geschrieben ist. Ich denke, es ist eine gute Angewohnheit, es so effizient wie möglich zu schreiben, anstatt das zu tun, was den schönsten Code ausmacht, oder es als schlechte Praxis zu betrachten, SQL dynamisch zu erstellen.
Ich habe gesehen, dass die Ausführung der Split-Funktionen in vielen Fällen, in denen die Parameter groß werden, länger dauert als die Abfrage selbst. Eine gespeicherte Prozedur mit Tabellenwertparametern in SQL 2008 ist die einzige andere Option, die ich in Betracht ziehen würde, obwohl dies in Ihrem Fall wahrscheinlich langsamer sein wird. TVP ist wahrscheinlich nur bei großen Listen schneller, wenn Sie nach dem Primärschlüssel des TVP suchen, da SQL ohnehin eine temporäre Tabelle für die Liste erstellt (wenn die Liste groß ist). Sie werden es nicht sicher wissen, wenn Sie es nicht testen.
Ich habe auch gespeicherte Prozeduren gesehen, die 500 Parameter mit den Standardwerten null und WHERE Column1 IN (@ Param1, @ Param2, @ Param3, ..., @ Param500) hatten. Dies führte dazu, dass SQL eine temporäre Tabelle erstellte, eine Sortierung / Unterscheidung durchführte und dann anstelle einer Indexsuche einen Tabellenscan durchführte. Dies ist im Wesentlichen das, was Sie tun würden, wenn Sie diese Abfrage parametrisieren, obwohl sie so klein ist, dass sie keinen spürbaren Unterschied macht. Ich empfehle dringend, NULL nicht in Ihren IN-Listen zu haben, da dies nicht wie beabsichtigt funktioniert, wenn dies in NOT IN geändert wird. Sie könnten die Parameterliste dynamisch erstellen, aber das einzig offensichtliche, was Sie gewinnen würden, ist, dass die Objekte den einfachen Anführungszeichen für Sie entgehen würden. Dieser Ansatz ist auch auf der Anwendungsseite etwas langsamer, da die Objekte die Abfrage analysieren müssen, um die Parameter zu finden.
Die Wiederverwendung von Ausführungsplänen für gespeicherte Prozeduren oder parametrisierte Abfragen kann zu einem Leistungsgewinn führen, bindet Sie jedoch an einen Ausführungsplan, der durch die erste ausgeführte Abfrage bestimmt wird. Dies kann in vielen Fällen für nachfolgende Abfragen weniger als ideal sein. In Ihrem Fall ist die Wiederverwendung von Ausführungsplänen wahrscheinlich ein Plus, aber es macht möglicherweise überhaupt keinen Unterschied, da das Beispiel eine wirklich einfache Abfrage ist.
Cliffs Notizen:
Für Ihren Fall macht alles, was Sie tun, sei es die Parametrisierung mit einer festen Anzahl von Elementen in der Liste (null, wenn nicht verwendet), das dynamische Erstellen der Abfrage mit oder ohne Parameter oder die Verwendung gespeicherter Prozeduren mit tabellenwertigen Parametern keinen großen Unterschied . Meine allgemeinen Empfehlungen lauten jedoch wie folgt:
Ihr Fall / einfache Fragen mit wenigen Parametern:
Dynamisches SQL, möglicherweise mit Parametern, wenn das Testen eine bessere Leistung zeigt.
Abfragen mit wiederverwendbaren Ausführungsplänen, die mehrmals aufgerufen werden, indem einfach die Parameter geändert werden oder wenn die Abfrage kompliziert ist:
SQL mit dynamischen Parametern.
Abfragen mit großen Listen:
Gespeicherte Prozedur mit Tabellenwertparametern. Wenn die Liste stark variieren kann, verwenden Sie WITH RECOMPILE für die gespeicherte Prozedur oder verwenden Sie einfach dynamisches SQL ohne Parameter, um einen neuen Ausführungsplan für jede Abfrage zu generieren.
quelle
Vielleicht können wir hier XML verwenden:
quelle
CTE
und@x
kann entfernt / in die Unterauswahl eingefügt werden, wenn dies sehr sorgfältig durchgeführt wird, wie in diesem Artikel gezeigt .Ich würde dies standardmäßig mit der Übergabe einer Tabellenwertfunktion (die eine Tabelle aus einer Zeichenfolge zurückgibt) an die IN-Bedingung angehen.
Hier ist der Code für die UDF (ich habe ihn irgendwo von Stack Overflow bekommen, ich kann die Quelle momentan nicht finden)
Sobald Sie dies erhalten haben, wäre Ihr Code so einfach:
Sofern Sie keine lächerlich lange Zeichenfolge haben, sollte dies mit dem Tabellenindex gut funktionieren.
Bei Bedarf können Sie es in eine temporäre Tabelle einfügen, indizieren und dann einen Join ausführen ...
quelle
Eine andere mögliche Lösung besteht darin, anstelle einer variablen Anzahl von Argumenten an eine gespeicherte Prozedur eine einzelne Zeichenfolge zu übergeben, die die Namen enthält, nach denen Sie suchen, sie jedoch eindeutig zu machen, indem Sie sie mit '<>' umgeben. Verwenden Sie dann PATINDEX, um die Namen zu finden:
quelle
Verwenden Sie die folgende gespeicherte Prozedur. Es verwendet eine benutzerdefinierte Aufteilungsfunktion, die hier zu finden ist .
quelle
Wenn in der IN-Klausel Zeichenfolgen mit dem Komma (,) getrennt sind, können wir die charindex-Funktion verwenden, um die Werte abzurufen. Wenn Sie .NET verwenden, können Sie mit SqlParameters zuordnen.
DDL-Skript:
T-SQL:
Sie können die obige Anweisung in Ihrem .NET-Code verwenden und den Parameter mit SqlParameter zuordnen.
Fiddler-Demo
BEARBEITEN: Erstellen Sie die Tabelle mit dem Namen SelectedTags mit dem folgenden Skript.
DDL-Skript:
T-SQL:
quelle
Für eine variable Anzahl solcher Argumente ist mir nur bekannt, dass Sie entweder explizit SQL generieren oder eine temporäre Tabelle mit den gewünschten Elementen füllen und mit der temporären Tabelle verknüpfen.
quelle
In ColdFusion machen wir einfach:
quelle
Hier ist eine Technik, mit der eine lokale Tabelle neu erstellt wird, die in einer Abfragezeichenfolge verwendet werden soll. Auf diese Weise werden alle Analyseprobleme beseitigt.
Die Zeichenfolge kann in einer beliebigen Sprache erstellt werden. In diesem Beispiel habe ich SQL verwendet, da dies das ursprüngliche Problem war, das ich zu lösen versuchte. Ich brauchte eine saubere Methode, um Tabellendaten im laufenden Betrieb in einer Zeichenfolge zu übergeben, die später ausgeführt werden sollte.
Die Verwendung eines benutzerdefinierten Typs ist optional. Das Erstellen des Typs wird nur einmal erstellt und kann im Voraus erfolgen. Andernfalls fügen Sie der Deklaration in der Zeichenfolge einfach einen vollständigen Tabellentyp hinzu.
Das allgemeine Muster ist einfach zu erweitern und kann zum Übergeben komplexerer Tabellen verwendet werden.
quelle
In SQL Server 2016+ besteht eine andere Möglichkeit darin, die
OPENJSON
Funktion zu verwenden.Über diesen Ansatz wird in OPENJSON gebloggt - eine der besten Möglichkeiten, Zeilen anhand der Liste der IDs auszuwählen .
Ein voll funktionsfähiges Beispiel unten
quelle
Hier ist eine andere Alternative. Übergeben Sie einfach eine durch Kommas getrennte Liste als Zeichenfolgenparameter an die gespeicherte Prozedur und:
Und die Funktion:
quelle
Ich habe eine Antwort, die keine UDF, XML erfordert. Da IN eine select-Anweisung akzeptiert, z. B. SELECT * FROM Test, wobei Data IN (SELECT Value FROM TABLE)
Sie brauchen wirklich nur eine Möglichkeit, die Zeichenfolge in eine Tabelle zu konvertieren.
Dies kann mit einem rekursiven CTE oder einer Abfrage mit einer Nummerntabelle (oder Master..spt_value) erfolgen.
Hier ist die CTE-Version.
quelle
Ich verwende eine präzisere Version der am besten bewerteten Antwort :
Die Tag-Parameter werden zweimal durchlaufen. Aber das spielt die meiste Zeit keine Rolle (es wird nicht Ihr Engpass sein; wenn ja, rollen Sie die Schleife ab).
Wenn Sie wirklich an Leistung interessiert sind und nicht zweimal durch die Schleife iterieren möchten, finden Sie hier eine weniger schöne Version:
quelle
Hier ist eine weitere Antwort auf dieses Problem.
(neue Version veröffentlicht am 04.06.13).
Prost.
quelle
Der einzige Gewinnzug ist, nicht zu spielen.
Keine unendliche Variabilität für Sie. Nur endliche Variabilität.
In SQL haben Sie eine Klausel wie diese:
Im C # -Code machen Sie ungefähr so:
Wenn also die Anzahl 0 ist, gibt es keinen Filter und alles geht durch. Wenn die Anzahl höher als 0 ist, muss der Wert in der Liste enthalten sein, aber die Liste wurde mit unmöglichen Werten auf fünf aufgefüllt (damit SQL immer noch Sinn macht).
Manchmal ist die lahme Lösung die einzige, die tatsächlich funktioniert.
quelle