Apakah ada cara yang lebih baik untuk membangun klausa SQL WHERE secara dinamis daripada menggunakan 1 = 1 di awal?

110

Saya sedang membangun beberapa kueri SQL di C #. Ini akan berbeda tergantung pada beberapa kondisi yang disimpan sebagai variabel dalam kode.

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 ";

Ini berhasil, tetapi pengujian 1 = 1 tampaknya tidak elegan. Jika saya tidak menggunakannya, saya harus mengingat dan memeriksa setiap kali apakah kata kunci "di mana" sudah ditambahkan atau tidak ke kueri.

Apakah ada solusi yang lebih baik?

RRM
sumber
118
Sejujurnya - Saya akan melakukannya seperti ini juga, tapi saya akan menggunakan 42 = 42;-)
fero
5
Saya sebenarnya selalu menulis pertanyaan saya seperti ini. Memudahkan untuk mengomentari suatu kondisi
Deruijter
4
@catfood Proyek pertama yang saya lakukan saat magang adalah menulis alat untuk membantu menganalisis kueri kinerja terhadap server Sybase kami. Penemuan yang lucu adalah ratusan ribu Select 42pertanyaan yang kami terima. (tidak lucu mencoba melacak sumber)
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- Itulah mengapa Anda menggunakan 1 = 1. Mesin database tetap mengoptimalkannya, jadi meskipun mungkin terlihat jelek, sejauh ini cara termudah untuk menyelesaikan masalah.
Robert Harvey
4
Meskipun jawaban yang diberikan sangat bagus, menurut saya kode asli Anda adalah yang paling mudah dibaca.
Uooo

Jawaban:

157

Simpan kondisi dalam daftar:

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

if (condition1) conditions.Add("Col1=0");
//...
if (conditions.Any())
    Query += " WHERE " + string.Join(" AND ", conditions.ToArray());
Ahmed KRAIEM
sumber
24
Solusi bagus, tetapi ToArray()tidak diperlukan dengan .NET 4 karena ada kelebihan beban yang menerima semua IEnumerable<string>.
fero
101
Saya senang dengan semua peluang injeksi SQL yang disediakan ini.
asteri
12
@Jeff Jika Anda tidak melakukan hard-coding nilai-nilai di klausa where Anda bisa saja memiliki daftar ke-2 dengan SqlParameters juga. Anda hanya perlu mengisi daftar itu pada saat yang sama dengan daftar kondisi dan memanggil AddRange (parameter.ToArray ()) di akhir.
Scott Chamberlain
5
@ScottChamberlain Ya, Anda juga dapat dengan mudah melepaskan string input sebelum memasukkannya ke dalam daftar. Saya kebanyakan hanya memperingatkan terhadap kemungkinan serangan menggunakan humor jenaka.
asteri
4
@Jeff itu hanya rentan terhadap injeksi SQL jika kondisinya termasuk input pengguna (contoh asli tidak)
D Stanley
85

Salah satu solusinya adalah dengan tidak menulis kueri secara manual dengan menambahkan string. Anda dapat menggunakan ORM, seperti Entity Framework , dan dengan LINQ ke Entitas menggunakan fitur yang ditawarkan bahasa dan framework:

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
sumber
@vaheeds Saya tidak mengerti pertanyaan itu. Keduanya adalah ORM yang berbeda.
CodeCaster
Maaf, saya sedang mencari untuk membandingkan kinerja necis dengan ORM lain, dan saya sampai di sini oleh Google, jadi saya pikir PrintResults(query)kueri yang dihasilkan kemudian akan digunakan dengan rapi sebagai kueri !!
vaheeds
@vaheeds baik-baik saja, tetapi tidak memahami jawaban tidak menjamin suara negatif. Jika itu adalah Anda, yang secara kebetulan terjadi bersamaan dengan komentar Anda.
CodeCaster
hak Anda, itu adalah kesalahpahaman. Saya menderita LINQ untuk entitas yang memiliki kinerja buruk pada kueri yang rumit. Saya mengkompensasi suara
negatif
Itu bukanlah jawaban untuk pertanyaan
HGMamaci
17

Sedikit berlebihan dalam kasus sederhana ini tetapi saya telah menggunakan kode yang mirip dengan ini di masa lalu.

Buat fungsi

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);
}

Gunakan seperti ini

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);

Dengan cara ini jika tidak ada kondisi yang ditemukan Anda bahkan tidak repot-repot memuat pernyataan where dalam kueri dan menyimpan sql server satu detik mikro untuk memproses junk where clause ketika mem-parsing pernyataan sql.

Alan Barber
sumber
Saya tidak melihat bagaimana ini membuatnya lebih elegan. Jelas tidak lebih jelas apa yang terjadi di sini. Saya dapat melihat penggunaan fungsi utilitas itu, tetapi tidak lebih elegan.
usr
memberi Anda satu suara untuk mencerahkan kami tentang pentingnya detik mikro
pengguna1451111
15

Ada solusi lain, yang mungkin juga tidak elegan, tetapi berfungsi dan menyelesaikan masalah:

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 "
}

Untuk:

  • daftar kondisi kosong, hasilnya akan sederhana SELECT * FROM Table1 ,
  • satu syarat saja SELECT * FROM Table1 WHERE cond1
  • setiap kondisi berikut akan menghasilkan tambahan AND condN
Dariusz
sumber
6
Itu menyisakan menggantung WHEREjika tidak ada predikat; 1 = 1 secara khusus ada untuk menghindari itu.
Gayus
Jadi beralihlah ke String query = "SELECT * FROM Table1";dan string jointer = " WHERE ";?
Brendan Long
@BrendanLong Lalu WHEREapakah ANDs harus ditempatkan di antara kondisi?
PenguinCoder
@PenguinCoder Sulit untuk menampilkan kode lengkap dalam komentar. Maksud saya mengganti string joinerbaris dengan string joiner = " WHERE ";, dan membiarkan joiner = " AND ";baris itu sendiri.
Brendan Long
@Gaius Saya mengasumsikan kodisinya tidak kosong, tetapi meletakkan WHERE di joiner harus melakukan trik. Terima kasih atas komentarnya!
Dariusz
11

Lakukan saja sesuatu seperti ini:

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);
}

Ini injeksi SQL aman dan IMHO , cukup bersih. The Remove()hanya menghilangkan yang terakhirAND ;

Ini berfungsi baik jika tidak ada kondisi yang ditetapkan, jika satu telah ditetapkan atau jika beberapa telah ditetapkan.

jgauffin.dll
sumber
1
Saya tidak yakin (jangan gunakan C # sendiri) tapi saya akan mengatakan itu conditions != nullselalu true, seperti yang Anda inisialisasi dengan ""(kecuali di C # "" == null). Ini mungkin harus menjadi cek, jika conditionstidak kosong… ;-)
siegi
9

Tambahkan saja dua baris di belakang.

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 ", "");

Misalnya

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

akan menjadi

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

Sementara

SELECT * FROM Table1 WHERE 1=1 

akan menjadi

SELECT * FROM Table1

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

Terima kasih telah menunjukkan kelemahan solusi ini:

"Ini dapat merusak kueri jika, karena alasan apa pun, salah satu ketentuan berisi teks" 1 = 1 AND "atau" WHERE 1 = 1 ". Ini dapat terjadi jika ketentuan berisi subkueri atau mencoba memeriksa apakah beberapa kolom berisi teks ini, misalnya. Mungkin ini bukan masalah dalam kasus Anda, tetapi Anda harus mengingatnya… "

Untuk mengatasi masalah ini, kita perlu membedakan "main" WHERE 1 = 1 dan yang dari subkueri, yang sangat mudah:

Cukup buat "main" WHERE spesial: Saya akan menambahkan tanda "$"

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 ";

Kemudian tetap tambahkan dua baris:

Query.Replace("WHERE$ 1=1 AND ", "WHERE ");
Query.Replace(" WHERE$ 1=1 ", "");
milesma
sumber
1
Ini bisa merusak kueri jika, karena alasan apa pun, salah satu kondisi berisi teks "1=1 AND "atau " WHERE 1=1 ". Ini bisa terjadi jika kondisi berisi subkueri atau mencoba memeriksa apakah beberapa kolom berisi teks ini, misalnya. Mungkin ini bukan masalah dalam kasus Anda, tetapi Anda harus mengingatnya…
siegi
8

Gunakan ini:

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
sumber
Jawaban ini akan berhasil, dan tidak ada yang salah dengan itu, tetapi menurut saya ini tidak lebih bersih dan sederhana daripada pertanyaan asli. Pencarian string QuerySubmenurut saya tidak lebih baik atau lebih buruk daripada menggunakan where 1=1hack. Tetapi ini adalah kontribusi yang bijaksana.
catfood
3
Ada kesalahan. Diperbaiki. Permintaan saya akan gagal jika tidak ada kondisi yang ada :-P Namun saya harus mengatakan bahwa Ahmed atau CodeCaster bagi saya adalah solusi terbaik. Saya hanya menyajikan alternatif untuk kalian!
Anshuman
Ini masih salah, secara umum. Misalkan itu ... FROM SOMETABLE WHERE ; laluTrimEnd akan benar-benar mengurangi ini menjadi ... FROM SOMETABL. Jika ini benar-benar a StringBuilder(yang seharusnya jika Anda memiliki banyak manipulasi string atau lebih) Anda bisa saja Query.Length -= "WHERE ".Length;.
Mark Hurd
Mark, berhasil. Saya telah mencoba ini di banyak proyek. Cobalah dan Anda akan menemukannya!
Anshuman
8
jelek sekali :) ditambah lagi bisa membuat hingga 7 string jika saya menghitung dengan benar
Piotr Perak
5

Mengapa tidak menggunakan Query Builder yang sudah ada? Sesuatu seperti Kata Sql .

Ini mendukung kondisi kompleks tempat, gabungan, dan subkueri.

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"))

ini bekerja dengan Sql Server, MySql dan PostgreSql.

amd
sumber
4

Solusi literal tercepat untuk apa yang Anda minta yang dapat saya pikirkan adalah ini:

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);

Tampaknya tidak elegan, pasti, saya akan merujuk Anda ke rekomendasi CodeCaster untuk menggunakan ORM. Tetapi jika Anda berpikir tentang apa yang dilakukan di sini, Anda benar-benar tidak khawatir tentang 'membuang' 4 karakter memori, dan sangat cepat bagi komputer untuk memindahkan penunjuk 4 tempat.

Jika Anda memiliki waktu untuk mempelajari cara menggunakan ORM, itu benar-benar dapat bermanfaat bagi Anda. Tetapi sehubungan dengan ini, jika Anda mencoba untuk menjaga kondisi tambahan itu agar tidak mencapai SQL db, ini akan melakukannya untuk Anda.

trevorgrayson
sumber
4

Jika ini adalah SQL Server , Anda dapat membuat kode ini lebih bersih.

Ini juga mengasumsikan sejumlah parameter yang diketahui, yang mungkin merupakan asumsi yang buruk ketika saya memikirkan kemungkinannya.

Di C #, Anda akan menggunakan:

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();
}

Dan kemudian di sisi SQL:

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
sumber
Menyembunyikan kolom Anda di dalam ekspresi dapat mencegah penggunaan indeks, dan teknik ini tidak disarankan karena alasan ini di sini .
bbsimonbb
itu penemuan yang menarik. Terima kasih atas infonya. akan memperbarui
mckeejm
3

Bergantung pada kondisinya, logika boolean mungkin dapat digunakan dalam kueri. Sesuatu seperti ini :

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
sumber
3

Saya suka antarmuka stringbuilder yang lancar, jadi saya membuat beberapa ExtensionMethods.

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
sumber
2

IMHO, saya pikir pendekatan Anda salah:

Membuat kueri database dengan menggabungkan string TIDAK PERNAH merupakan ide yang baik (risiko injeksi SQL dan kode dapat dengan mudah dipatahkan jika Anda melakukan beberapa perubahan di tempat lain).

Anda dapat menggunakan ORM (Saya menggunakan NHibernate ) atau setidaknya menggunakanSqlCommand.Parameters

Jika Anda benar-benar ingin menggunakan penggabungan string, saya akan menggunakan a StringBuilder(ini adalah objek yang tepat untuk penggabungan string):

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;

Sebagai pemikiran terakhir, Where 1=1ini benar-benar jelek tetapi SQL Server akan tetap mengoptimalkannya.

giammin
sumber
SELECT * FROM Table1 WHERE AND Col1=0tampaknya tidak benar, yang merupakan inti dari WHERE 1=1.
Mormegil
2

Dapper SqlBuilder adalah opsi yang cukup bagus. Ini bahkan digunakan dalam produksi di StackOverflow.

Baca entri blog Sam tentang itu .

Sejauh yang saya tahu, ini bukan bagian dari paket Nuget, jadi Anda harus menyalin dan menempelkan kodenya ke dalam proyek Anda atau mengunduh sumber Dapper dan membangun proyek SqlBuilder. Apa pun itu, Anda juga perlu merujuk Dapper untuk DynamicParameterskelas tersebut.

Ronnie Overby
sumber
1
Saya tidak berpikir bahwa SqlBuilder Dapper termasuk dalam paket itu.
Ronnie Overby
1

Saya melihat ini digunakan sepanjang waktu di Oracle sambil membangun SQL dinamis dalam prosedur yang tersimpan . Saya menggunakannya dalam kueri sambil menjelajahi masalah data juga hanya untuk membuat peralihan di antara filter data yang berbeda lebih cepat ... Cukup beri komentar atau tambahkan kembali dengan mudah.

Menurut saya, ini cukup umum dan cukup mudah untuk dipahami oleh seseorang yang meninjau kode Anda.

Don Boling
sumber
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 ");
    }
}

Realisasi dengan metode penyuluhan.

    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
sumber
AKAN MELAWAN GRAIN!
Ronnie Overby
Permisi? Apa maksudmu?
Maxim Zhukov
0

Menggunakan stringfungsi Anda juga dapat melakukannya dengan cara ini:

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  

Saya pribadi merasa mudah untuk menghapus elemen kondisional di bagian akhir, karena posisinya mudah diprediksi.

NeverHopeless
sumber
0

Saya memikirkan solusi yang mungkin lebih mudah dibaca:

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"));

Saya hanya tidak yakin apakah interpreter SQL juga akan mengoptimalkan Col1 = Col1kondisi (dicetak ketika condition1salah).

CodeCaster
sumber
0

Berikut cara yang lebih elegan:

    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
sumber
0

Seperti yang telah dinyatakan, membuat SQL dengan penggabungan bukanlah ide yang bagus . Bukan hanya karena injeksi SQL. Sebagian besar karena itu jelek, sulit dirawat dan sama sekali tidak perlu . Anda harus menjalankan program Anda dengan jejak atau debug untuk melihat SQL apa yang dihasilkannya. Jika Anda menggunakan QueryFirst (disclaimer: yang saya tulis) godaan yang tidak menyenangkan akan dihapus, dan Anda bisa langsung melakukannya di SQL.

Halaman ini memiliki cakupan komprehensif tentang opsi TSQL untuk menambahkan predikat pencarian secara dinamis. Opsi berikut berguna untuk situasi di mana Anda ingin membiarkan pilihan kombinasi predikat pencarian kepada pengguna Anda.

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 memberi Anda C # null ke db NULL, jadi Anda cukup memanggil metode Execute () dengan nulls jika sesuai, dan semuanya akan berfungsi. <opinion> Mengapa C # dev sangat enggan melakukan hal-hal di SQL, meski lebih sederhana. Pikiran mengejutkan. </opinion>

bbsimonbb
sumber
0

Untuk langkah-langkah pemfilteran yang lebih lama, StringBuilder adalah pendekatan yang lebih baik seperti yang dikatakan banyak orang.

dalam kasus Anda, saya akan pergi dengan:

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
sumber
0

Ringkas, elegan dan manis, seperti yang ditunjukkan pada gambar di bawah ini.

masukkan deskripsi gambar di sini

pengguna1451111
sumber