Gibt es eine bessere Möglichkeit, eine SQL WHERE-Klausel dynamisch zu erstellen, als am Anfang 1 = 1 zu verwenden?

110

Ich erstelle eine SQL- Abfrage in C #. Dies hängt von einigen Bedingungen ab, die als Variablen im Code gespeichert sind.

string Query="SELECT * FROM Table1 WHERE 1=1 ";
if (condition1) 
    Query += "AND Col1=0 ";
if (condition2) 
    Query += "AND Col2=1 ";
if (condition3) 
    Query += "AND Col3=2 ";

Es funktioniert, aber das Testen von 1 = 1 scheint nicht elegant zu sein. Wenn ich es nicht verwenden würde, müsste ich mich jedes Mal daran erinnern und prüfen, ob der Abfrage bereits das Schlüsselwort "where" hinzugefügt wurde oder nicht.

Gibt es eine schönere Lösung?

RRM
quelle
118
Um ehrlich zu sein - ich würde es auch so machen, aber ich würde es benutzen 42 = 42;-)
fero
5
Ich schreibe meine Anfragen eigentlich immer so. Erleichtert das
Auskommentieren
4
@catfood Das erste Projekt, an dem ich als Praktikant teilgenommen habe, war das Schreiben von Tools zur Analyse der Leistungsabfragen auf unseren Sybase-Servern. Eine amüsante Entdeckung waren die hunderttausenden Select 42Anfragen, die wir erhielten. (nicht amüsant war der Versuch, die Quelle aufzuspüren)
Mr.Mindor
24
If I didn't use it, I would have to remember and check every time if "where" keyword was already added or not to the query- Deshalb benutzt du 1 = 1. Das Datenbankmodul optimiert es trotzdem, so dass es zwar hässlich aussieht, aber bei weitem der einfachste Weg ist, das Problem zu lösen.
Robert Harvey
4
Obwohl die gegebenen Antworten sehr nett sind, denke ich, dass Ihr Originalcode am einfachsten zu lesen ist.
Uooo

Antworten:

157

Speichern Sie die Bedingungen in einer Liste:

List<string> conditions = new List<string>();

if (condition1) conditions.Add("Col1=0");
//...
if (conditions.Any())
    Query += " WHERE " + string.Join(" AND ", conditions.ToArray());
Ahmed KRAIEM
quelle
24
Gute Lösung, aber das ToArray()ist bei .NET 4 nicht erforderlich, da es eine Überlastung gibt, die keine akzeptiert IEnumerable<string>.
Fero
101
Ich freue mich über alle SQL-Injection-Möglichkeiten, die sich daraus ergeben.
Asteri
12
@Jeff Wenn Sie die Werte in der where-Klausel nicht fest codieren, können Sie auch eine zweite Liste mit SqlParameters erstellen. Sie müssen diese Liste nur gleichzeitig mit der Bedingungsliste füllen und am Ende AddRange (parameters.ToArray ()) aufrufen .
Scott Chamberlain
5
@ScottChamberlain Ja, Sie können die Eingabezeichenfolgen auch einfach umgehen, bevor Sie sie in die Liste aufnehmen. Ich warnte meistens nur vor einem möglichen Angriff mit scherzhaftem Humor.
Asteri
4
@ Jeff es ist nur anfällig für SQL-Injection, wenn die Bedingungen Benutzereingaben enthalten (das ursprüngliche Beispiel nicht)
D Stanley
85

Eine Lösung besteht darin, Abfragen einfach nicht manuell durch Anhängen von Zeichenfolgen zu schreiben. Sie können ein ORM wie Entity Framework verwenden und mit LINQ to Entities die Funktionen verwenden, die Ihnen die Sprache und das Framework bieten:

using (var dbContext = new MyDbContext())
{
    IQueryable<Table1Item> query = dbContext.Table1;

    if (condition1)
    {
        query = query.Where(c => c.Col1 == 0);
    }
    if (condition2)
    {
        query = query.Where(c => c.Col2 == 1);
    }
    if (condition3)
    {
        query = query.Where(c => c.Col3 == 2);
    }   

    PrintResults(query);
}
CodeCaster
quelle
@vaheeds Ich verstehe diese Frage nicht. Beide sind unterschiedliche ORMs.
CodeCaster
Entschuldigung, ich habe gesucht, um die Leistung von Dapper mit anderen ORMs zu vergleichen, und ich komme hierher über Google, also dachte ich, dass die generierte PrintResults(query)Abfrage dann in Dapper als Abfrage verwendet wird !!
Vaheeds
@vaheeds in Ordnung, aber das Nichtverstehen einer Antwort rechtfertigt keine Ablehnung. Wenn das du wärst, was zufällig gleichzeitig mit deinem Kommentar passiert ist.
CodeCaster
Ihr Recht, das war ein Missverständnis. Ich leide unter der schlechten Leistung von Linq to Entities bei komplizierten Abfragen. Ich habe die
Abwärtsabstimmung
Das ist keine Antwort auf die Frage
HGMamaci
17

Ein bisschen übertrieben in diesem einfachen Fall, aber ich habe in der Vergangenheit ähnlichen Code verwendet.

Erstellen Sie eine Funktion

string AddCondition(string clause, string appender, string condition)
{
    if (clause.Length <= 0)
    {
        return String.Format("WHERE {0}",condition);
    }
    return string.Format("{0} {1} {2}", clause, appender, condition);
}

Verwenden Sie es so

string query = "SELECT * FROM Table1 {0}";
string whereClause = string.Empty;

if (condition 1)
    whereClause = AddCondition(whereClause, "AND", "Col=1");

if (condition 2)
    whereClause = AddCondition(whereClause, "AND", "Col2=2");

string finalQuery = String.Format(query, whereClause);

Auf diese Weise müssen Sie, wenn keine Bedingungen gefunden werden, nicht einmal eine where-Anweisung in die Abfrage laden und dem SQL-Server eine Mikrosekunde Zeit sparen, um die Junk-where-Klausel zu verarbeiten, wenn die SQL-Anweisung analysiert wird.

Alan Barber
quelle
Ich sehe nicht, wie das es eleganter macht. Es ist sicherlich nicht klarer, was hier los ist. Ich kann die Verwendung dieser Utility-Funktion sehen, aber sie ist nicht eleganter.
usr
gab Ihnen eine Stimme für die Aufklärung über die Bedeutung einer
Mikrosekunde
15

Es gibt eine andere Lösung, die vielleicht auch nicht elegant ist, aber funktioniert und das Problem löst:

String query = "SELECT * FROM Table1";
List<string> conditions = new List<string>();
// ... fill the conditions
string joiner = " WHERE ";
foreach (string condition in conditions) {
  query += joiner + condition;
  joiner = " AND "
}

Zum:

  • leere Bedingungsliste, das Ergebnis wird einfach sein SELECT * FROM Table1,
  • eine einzige Bedingung wird es sein SELECT * FROM Table1 WHERE cond1
  • Jede folgende Bedingung generiert zusätzliche AND condN
Dariusz
quelle
6
Das lässt baumeln, WHEREwenn es keine Prädikate gibt; Das 1 = 1 existiert speziell, um dies zu vermeiden.
Gaius
Also zu String query = "SELECT * FROM Table1";und wechseln string jointer = " WHERE ";?
Brendan Long
@BrendanLong Dann WHEREsollen die ANDs zwischen Bedingungen gestellt werden?
PenguinCoder
@PenguinCoder Es ist schwierig, den vollständigen Code in einem Kommentar anzuzeigen. Ich wollte die string joinerLeitung durch ersetzen string joiner = " WHERE ";und die joiner = " AND ";Leitung in Ruhe lassen.
Brendan Long
@Gaius Ich nahm an, dass die Codierungen nicht leer sind, aber WHERE in Joiner zu setzen sollte den Trick tun. Danke für die Bemerkung!
Dariusz
11

Mach einfach so etwas:

using (var command = connection.CreateCommand())
{
    command.CommandText = "SELECT * FROM Table1";

    var conditions = "";
    if (condition1)
    {    
        conditions += "Col1=@val1 AND ";
        command.AddParameter("val1", 1);
    }
    if (condition2)
    {    
        conditions += "Col2=@val2 AND ";
        command.AddParameter("val2", 1);
    }
    if (condition3)
    {    
        conditions += "Col3=@val3 AND ";
        command.AddParameter("val3", 1);
    }
    if (conditions != "")
        command.CommandText += " WHERE " + conditions.Remove(conditions.Length - 5);
}

Es ist SQL Injection Safe und meiner Meinung nach ziemlich sauber. Das Remove()entfernt einfach das letzte AND;

Es funktioniert sowohl, wenn keine Bedingungen festgelegt wurden, wenn eine festgelegt wurde oder wenn mehrere festgelegt wurden.

jgauffin
quelle
1
Ich bin mir nicht sicher (benutze C # nicht selbst), aber ich würde sagen, das conditions != nullist immer so true, wenn du es mit initialisierst ""(außer in C # "" == null). Es sollte wahrscheinlich ein Scheck sein, wenn conditionsnicht leer ist… ;-)
siegi
9

Fügen Sie einfach zwei Zeilen hinten hinzu.

string Query="SELECT * FROM Table1 WHERE 1=1 ";
if (condition1) Query+="AND Col1=0 ";
if (condition2) Query+="AND Col2=1 ";
if (condition3) Query+="AND Col3=2 ";
Query.Replace("1=1 AND ", "");
Query.Replace(" WHERE 1=1 ", "");

Z.B

SELECT * FROM Table1 WHERE 1=1 AND Col1=0 AND Col2=1 AND Col3=2 

wird zu werden

SELECT * FROM Table1 WHERE Col1=0 AND Col2=1 AND Col3=2 

Während

SELECT * FROM Table1 WHERE 1=1 

wird zu werden

SELECT * FROM Table1

=====================================

Vielen Dank, dass Sie auf einen Fehler dieser Lösung hingewiesen haben:

"Dies könnte die Abfrage unterbrechen, wenn eine der Bedingungen aus irgendeinem Grund den Text" 1 = 1 AND "oder" WHERE 1 = 1 "enthält. Dies kann der Fall sein, wenn die Bedingung eine Unterabfrage enthält oder versucht, zu überprüfen, ob welche vorhanden sind Die Spalte enthält beispielsweise diesen Text. Vielleicht ist dies in Ihrem Fall kein Problem, aber Sie sollten es berücksichtigen ... "

Um dieses Problem zu beseitigen, müssen wir das "Haupt" WHERE 1 = 1 von denen der Unterabfrage unterscheiden, was einfach ist:

Machen Sie einfach das "main" WHERE zu etwas Besonderem: Ich würde ein "$" - Zeichen anhängen

string Query="SELECT * FROM Table1 WHERE$ 1=1 ";
if (condition1) Query+="AND Col1=0 ";
if (condition2) Query+="AND Col2=1 ";
if (condition3) Query+="AND Col3=2 ";

Dann noch zwei Zeilen anhängen:

Query.Replace("WHERE$ 1=1 AND ", "WHERE ");
Query.Replace(" WHERE$ 1=1 ", "");
Milesma
quelle
1
Dies kann die Abfrage unterbrechen, wenn aus irgendeinem Grund eine der Bedingungen den Text "1=1 AND "oder enthält " WHERE 1=1 ". Dies kann beispielsweise der Fall sein, wenn die Bedingung eine Unterabfrage enthält oder versucht zu überprüfen, ob eine Spalte diesen Text enthält. Vielleicht ist dies in Ihrem Fall kein Problem, aber Sie sollten es im Auge behalten ...
siegi
8

Benutze das:

string Query="SELECT * FROM Table1 WHERE ";
string QuerySub;
if (condition1) QuerySub+="AND Col1=0 ";
if (condition2) QuerySub+="AND Col2=1 ";
if (condition3) QuerySub+="AND Col3=2 ";

if (QuerySub.StartsWith("AND"))
    QuerySub = QuerySub.TrimStart("AND".ToCharArray());

Query = Query + QuerySub;

if (Query.EndsWith("WHERE "))
    Query = Query.TrimEnd("WHERE ".ToCharArray());
Anshuman
quelle
Diese Antwort wird funktionieren, und es gibt nichts wirklich falsch, aber ich glaube nicht , dass es mehr sauber und einfach als die ursprüngliche Frage. Das Suchen von Strings QuerySubist meiner Meinung nach nicht besser oder schlechter als das Verwenden des where 1=1Hacks. Aber es ist ein nachdenklicher Beitrag.
Katzenfutter
3
Es gab einen Fehler. Korrigierte es. Meine Anfrage wäre bombardiert worden, wenn keine der Bedingungen gegeben wäre :-P Trotzdem muss ich sagen, dass Ahmeds oder CodeCasters für mich die besten Lösungen sind. Ich habe nur eine Alternative für euch vorgestellt!
Anshuman
Dies ist im Allgemeinen immer noch falsch. Angenommen, es war ... FROM SOMETABLE WHERE ; dann TrimEndwürde das das eigentlich reduzieren auf ... FROM SOMETABL. Wenn dies tatsächlich ein war StringBuilder(was es sein sollte, wenn Sie über so viel String-Manipulation oder mehr haben), können Sie einfach Query.Length -= "WHERE ".Length;.
Mark Hurd
Mark, es funktioniert. Ich habe dies in vielen Projekten versucht. Probieren Sie es aus und Sie werden feststellen, dass es funktioniert!
Anshuman
8
hässlich wie die Hölle :) und es kann bis zu 7 Saiten erzeugen, wenn ich richtig gezählt habe
Piotr Perak
5

Warum nicht einen vorhandenen Query Builder verwenden? So etwas wie Sql Kata .

Es unterstützt komplexe Where-Bedingungen, Joins und Unterabfragen.

var query = new Query("Users").Where("Score", ">", 100).OrderByDesc("Score").Limit(100);

if(onlyActive)
{
   query.Where("Status", "active")
}

// or you can use the when statement

query.When(onlyActive, q => q.Where("Status", "active"))

Es funktioniert mit SQL Server, MySQL und PostgreSql.

amd
quelle
4

Die schnellste wörtliche Lösung für das, was Sie sich vorstellen können, ist folgende:

string Query="SELECT * FROM Table1";
string Conditions = "";

if (condition1) Conditions+="AND Col1=0 ";
if (condition2) Conditions+="AND Col2=1 ";
if (condition3) Conditions+="AND Col3=2 ";

if (Conditions.Length > 0) 
  Query+=" WHERE " + Conditions.Substring(3);

Es scheint nicht elegant zu sein, worauf ich Sie auf die Empfehlung von CodeCaster zur Verwendung eines ORM verweisen würde. Aber wenn Sie darüber nachdenken, was dies hier tut, sind Sie wirklich nicht besorgt darüber, 4 Zeichen Speicher zu verschwenden, und es ist für einen Computer sehr schnell, einen Zeiger um 4 Stellen zu bewegen.

Wenn Sie die Zeit haben, den Umgang mit einem ORM zu lernen, könnte sich dies für Sie wirklich auszahlen. Wenn Sie jedoch versuchen, zu verhindern, dass diese zusätzliche Bedingung die SQL-Datenbank erreicht, wird dies für Sie erledigt.

Trevorgrayson
quelle
4

Wenn dies SQL Server ist , können Sie diesen Code viel sauberer machen.

Dies setzt auch eine bekannte Anzahl von Parametern voraus, was eine schlechte Annahme sein kann, wenn ich über die Möglichkeiten nachdenke.

In C # würden Sie verwenden:

using (SqlConnection conn = new SqlConnection("connection string"))
{
    conn.Open();
    SqlCommand command = new SqlCommand()
    {
        CommandText = "dbo.sample_proc",
        Connection = conn,
        CommandType = CommandType.StoredProcedure
    };

    if (condition1)
        command.Parameters.Add(new SqlParameter("Condition1", condition1Value));
    if (condition2)
        command.Parameters.Add(new SqlParameter("Condition2", condition2Value));
    if (condition3)
        command.Parameters.Add(new SqlParameter("Condition3", condition3Value));

    IDataReader reader = command.ExecuteReader();

    while(reader.Read())
    {
    }

    conn.Close();
}

Und dann auf der SQL-Seite:

CREATE PROCEDURE dbo.sample_proc
(
    --using varchar(50) generically
    -- "= NULL" makes them all optional parameters
    @Condition1 varchar(50) = NULL
    @Condition2 varchar(50) = NULL
    @Condition3 varchar(50) = NULL
)
AS
BEGIN
    /*
    check that the value of the parameter 
    matches the related column or that the 
    parameter value was not specified.  This
    works as long as you are not querying for 
    a specific column to be null.*/
    SELECT *
    FROM SampleTable
    WHERE (Col1 = @Condition1 OR @Condition1 IS NULL)
    AND   (Col2 = @Condition2 OR @Condition2 IS NULL)
    AND   (Col3 = @Condition3 OR @Condition3 IS NULL)
    OPTION (RECOMPILE)
    --OPTION(RECOMPILE) forces the query plan to remain effectively uncached
END
mckeejm
quelle
Das Ausblenden Ihrer Spalten in einem Ausdruck kann die Verwendung von Indizes verhindern. Aus diesem Grund wird hier von dieser Technik abgeraten .
Bbsimonbb
Das ist ein interessanter Fund. Danke für diese Info. wird aktualisiert
mckeejm
3

Abhängig von der Bedingung kann möglicherweise eine boolesche Logik in der Abfrage verwendet werden. Etwas wie das :

string Query="SELECT * FROM Table1  " +
             "WHERE (condition1 = @test1 AND Col1=0) "+
             "AND (condition2 = @test2 AND Col2=1) "+
             "AND (condition3 = @test3 AND Col3=2) ";
Rémi
quelle
3

Ich mag die fließende Oberfläche von Stringbuilder, deshalb habe ich einige ExtensionMethods erstellt.

var query = new StringBuilder()
    .AppendLine("SELECT * FROM products")
    .AppendWhereIf(!String.IsNullOrEmpty(name), "name LIKE @name")
    .AppendWhereIf(category.HasValue, "category = @category")
    .AppendWhere("Deleted = @deleted")
    .ToString();

var p_name = GetParameter("@name", name);
var p_category = GetParameter("@category", category);
var p_deleted = GetParameter("@deleted", false);
var result = ExecuteDataTable(query, p_name, p_category, p_deleted);


// in a seperate static class for extensionmethods
public StringBuilder AppendLineIf(this StringBuilder sb, bool condition, string value)
{
    if(condition)
        sb.AppendLine(value);
    return sb;
}

public StringBuilder AppendWhereIf(this StringBuilder sb, bool condition, string value)
{
    if (condition)
        sb.AppendLineIf(condition, sb.HasWhere() ? " AND " : " WHERE " + value);
    return sb;
}

public StringBuilder AppendWhere(this StringBuilder sb, string value)
{
    sb.AppendWhereIf(true, value);
    return sb;
}

public bool HasWhere(this StringBuilder sb)
{
    var seperator = new string [] { Environment.NewLine };
    var lines = sb.ToString().Split(seperator, StringSplitOptions.None);
    return lines.Count > 0 && lines[lines.Count - 1].Contains("where", StringComparison.InvariantCultureIgnoreCase);
}

// http://stackoverflow.com/a/4217362/98491
public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    return source.IndexOf(toCheck, comp) >= 0;
}
Jürgen Steinblock
quelle
2

IMHO, ich denke, dass Ihr Ansatz falsch ist:

Das Abfragen der Datenbank durch Verketten von Zeichenfolgen ist NIE eine gute Idee (das Risiko einer SQL-Injection und des Codes kann leicht beschädigt werden, wenn Sie an anderer Stelle Änderungen vornehmen).

Sie können ein ORM verwenden (ich verwende NHibernate ) oder zumindest verwendenSqlCommand.Parameters

Wenn Sie unbedingt die Verkettung von Zeichenfolgen verwenden möchten, würde ich a verwenden StringBuilder(dies ist das richtige Objekt für die Verkettung von Zeichenfolgen):

var query = new StringBuilder("SELECT * FROM Table1 WHERE");
int qLength = query.Length;//if you don't want to count :D
if (Condition1) query.Append(" Col1=0 AND");
if (Condition2) query.Append(" Col2=0 AND");
....
//if no condition remove WHERE or AND from query
query.Length -= query.Length == qLength ? 6 : 4;

Wie der letzte Gedanke ist, Where 1=1ist wirklich hässlich, aber SQL Server wird es trotzdem optimieren.

Giammin
quelle
SELECT * FROM Table1 WHERE AND Col1=0scheint nicht richtig zu sein, worum es geht WHERE 1=1.
Mormegil
2

Der Dapper SqlBuilder ist eine ziemlich gute Option. Es wird sogar in der Produktion von StackOverflow verwendet.

Lesen Sie Sams Blogeintrag darüber .

Soweit ich weiß, ist es nicht Teil eines Nuget-Pakets. Sie müssen also den Code kopieren, in Ihr Projekt einfügen oder die Dapper-Quelle herunterladen und das SqlBuilder-Projekt erstellen. In beiden Fällen müssen Sie auch auf Dapper für die DynamicParametersKlasse verweisen .

Ronnie Overby
quelle
1
Ich glaube nicht, dass Dappers SqlBuilder in diesem Paket enthalten ist.
Ronnie Overby
1

Ich sehe, dass dies in Oracle ständig verwendet wird, während dynamisches SQL in gespeicherten Prozeduren erstellt wird . Ich verwende es auch bei Abfragen, während ich Datenprobleme untersuche, um den Wechsel zwischen verschiedenen Datenfiltern zu beschleunigen ... Kommentieren Sie einfach eine Bedingung aus oder fügen Sie sie einfach wieder hinzu.

Ich finde es ziemlich häufig und leicht zu verstehen, wenn jemand Ihren Code überprüft.

Don Boling
quelle
1
public static class Ext
{
    public static string addCondition(this string str, bool condition, string statement)
    {
        if (!condition)
            return str;

        return str + (!str.Contains(" WHERE ") ? " WHERE " : " ") + statement;
    }

    public static string cleanCondition(this string str)
    {
        if (!str.Contains(" WHERE "))
            return str;

        return str.Replace(" WHERE AND ", " WHERE ").Replace(" WHERE OR ", " WHERE ");
    }
}

Realisierung mit Erweiterungsmethoden.

    static void Main(string[] args)
    {
        string Query = "SELECT * FROM Table1";

        Query = Query.addCondition(true == false, "AND Column1 = 5")
            .addCondition(18 > 17, "AND Column2 = 7")
            .addCondition(42 == 1, "OR Column3 IN (5, 7, 9)")
            .addCondition(5 % 1 > 1 - 4, "AND Column4 = 67")
            .addCondition(Object.Equals(5, 5), "OR Column5 >= 0")
            .cleanCondition();

        Console.WriteLine(Query);
    }
Maxim Zhukov
quelle
GEGEN DAS KORN GEHEN!
Ronnie Overby
Mich exekutieren? Was meinst du?
Maxim Zhukov
0

Mit der stringFunktion können Sie dies auch folgendermaßen tun:

string Query = "select * from Table1";

if (condition1) WhereClause += " Col1 = @param1 AND "; // <---- put conditional operator at the end
if (condition2) WhereClause += " Col1 = @param2 OR ";

WhereClause = WhereClause.Trim();

if (!string.IsNullOrEmpty(WhereClause))
    Query = Query + " WHERE " + WhereClause.Remove(WhereClause.LastIndexOf(" "));
// else
// no condition meets the criteria leave the QUERY without a WHERE clause  

Ich persönlich fühle mich leicht, die bedingten Elemente am Ende zu entfernen, da ihre Position leicht vorherzusagen ist.

NeverHopeless
quelle
0

Ich dachte an eine Lösung, die vielleicht etwas lesbarer ist:

string query = String.Format("SELECT * FROM Table1 WHERE "
                             + "Col1 = {0} AND "
                             + "Col2 = {1} AND "
                             + "Col3 = {2}",
                            (!condition1 ? "Col1" : "0"),
                            (!condition2 ? "Col2" : "1"),
                            (!condition3 ? "Col3" : "2"));

Ich bin mir nur nicht sicher, ob der SQL-Interpreter auch die Col1 = Col1Bedingung optimiert (gedruckt, wenn condition1falsch).

CodeCaster
quelle
0

Hier ist ein eleganterer Weg:

    private string BuildQuery()
    {
        string MethodResult = "";
        try
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("SELECT * FROM Table1");

            List<string> Clauses = new List<string>();

            Clauses.Add("Col1 = 0");
            Clauses.Add("Col2 = 1");
            Clauses.Add("Col3 = 2");

            bool FirstPass = true;

            if(Clauses != null && Clauses.Count > 0)
            {
                foreach(string Clause in Clauses)
                {
                    if (FirstPass)
                    {
                        sb.Append(" WHERE ");

                        FirstPass = false;

                    }
                    else
                    {
                        sb.Append(" AND ");

                    }

                    sb.Append(Clause);

                }

            }

            MethodResult = sb.ToString();

        }
        catch //(Exception ex)
        {
            //ex.HandleException()
        }
        return MethodResult;
    }
WonderWorker
quelle
0

Wie bereits erwähnt, ist das Erstellen von SQL durch Verkettung niemals eine gute Idee . Nicht nur wegen der SQL-Injection. Meistens, weil es nur hässlich, schwer zu warten und völlig unnötig ist . Sie müssen Ihr Programm mit Trace oder Debug ausführen, um zu sehen, welches SQL es generiert. Wenn Sie QueryFirst verwenden (Haftungsausschluss: den ich geschrieben habe), wird die unglückliche Versuchung beseitigt, und Sie können direkt in SQL vorgehen.

Diese Seite bietet eine umfassende Beschreibung der TSQL-Optionen zum dynamischen Hinzufügen von Suchprädikaten. Die folgende Option ist praktisch für Situationen, in denen Sie die Auswahl der Kombinationen von Suchprädikaten Ihrem Benutzer überlassen möchten.

select * from table1
where (col1 = @param1 or @param1 is null)
and (col2 = @param2 or @param2 is null)
and (col3 = @param3 or @param3 is null)
OPTION (RECOMPILE)

QueryFirst gibt Ihnen C # null bis db NULL, also rufen Sie einfach die Execute () -Methode mit Nullen auf, wenn dies angebracht ist, und alles funktioniert einfach. <opinion> Warum zögern C # -Entwickler so sehr, Dinge in SQL zu tun, selbst wenn es einfacher ist? Mind buddgles. </ Opinion>

bbsimonbb
quelle
0

Für längere Filterschritte ist StringBuilder der bessere Ansatz, wie viele sagen.

Auf Ihren Fall würde ich gehen mit:

StringBuilder sql = new StringBuilder();

if (condition1) 
    sql.Append("AND Col1=0 ");
if (condition2) 
    sql.Append("AND Col2=1 ");
if (condition3) 
    sql.Append("AND Col3=2 ");

string Query = "SELECT * FROM Table1 ";
if(sql.Length > 0)
 Query += string.Concat("WHERE ", sql.ToString().Substring(4)); //avoid first 4 chars, which is the 1st "AND "
HGMamaci
quelle
0

Prägnant, elegant und süß, wie im Bild unten gezeigt.

Geben Sie hier die Bildbeschreibung ein

user1451111
quelle