Có cách nào tốt hơn để tạo động một mệnh đề SQL WHERE hơn là sử dụng 1 = 1 ở đầu của nó không?


110

Tôi đang tạo một số truy vấn SQL trong C #. Nó sẽ khác nhau tùy thuộc vào một số điều kiện được lưu trữ dưới dạng các biến trong mã.

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

Nó hoạt động, nhưng thử nghiệm 1 = 1 có vẻ không thanh lịch. Nếu tôi không sử dụng nó, tôi sẽ phải nhớ và kiểm tra mọi lúc xem từ khóa "where" đã được thêm vào truy vấn hay chưa.

Có một giải pháp tốt hơn?


118
Thành thật mà nói - Tôi sẽ làm điều đó như thế này, quá, nhưng tôi sẽ sử dụng 42 = 42;-)
fero

5
Tôi thực sự luôn viết các truy vấn của mình như thế này. Làm cho nó dễ dàng hơn để nhận xét ra một điều kiện
Deruijter

4
@catfood Dự án đầu tiên mà tôi tham gia khi còn là một thực tập sinh là viết các công cụ để giúp phân tích các truy vấn hiệu suất trên các máy chủ Sybase của chúng tôi. Một khám phá thú vị là hàng trăm nghìn Select 42truy vấn mà chúng tôi nhận được. (không gây cười đã cố gắng để theo dõi các nguồn)
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- Đó là lý do tại sao bạn sử dụng 1 = 1. Công cụ cơ sở dữ liệu dù sao cũng tối ưu hóa nó, vì vậy mặc dù nó có thể trông xấu xí, nhưng cho đến nay đây là cách dễ nhất để giải quyết vấn đề.
Robert Harvey

4
Mặc dù các câu trả lời đưa ra rất hay, nhưng tôi nghĩ mã gốc của bạn là dễ đọc nhất.
Uooo

Câu trả lời:


157

Lưu các điều kiện trong một danh sách:

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

if (condition1) conditions.Add("Col1=0");
//...
if (conditions.Any())
    Query += " WHERE " + string.Join(" AND ", conditions.ToArray());

24
Giải pháp tốt, nhưng ToArray()không cần thiết với .NET 4 vì có quá tải chấp nhận bất kỳ IEnumerable<string>.
fero

101
Tôi rất vui vì tất cả các cơ hội tiêm SQL mà điều này cung cấp.
asteri

12
@Jeff Nếu bạn không mã hóa các giá trị trong mệnh đề where, bạn cũng có thể có danh sách thứ 2 với SqlParameters. Bạn chỉ cần điền danh sách đó cùng lúc với danh sách điều kiện và gọi AddRange (tham số.ToArray ()) ở cuối.
Scott Chamberlain

5
@ScottChamberlain Vâng, bạn cũng có thể chỉ cần thoát các chuỗi nhập trước khi đưa chúng vào danh sách. Tôi chủ yếu chỉ cảnh báo về một cuộc tấn công có thể xảy ra bằng cách sử dụng sự hài hước khó chịu.
asteri

4
@Jeff nó chỉ dễ bị chèn SQL nếu các điều kiện bao gồm đầu vào của người dùng (ví dụ ban đầu thì không)
D Stanley

85

Một giải pháp đơn giản là không viết truy vấn theo cách thủ công bằng cách nối các chuỗi. Bạn có thể sử dụng ORM, như Khung thực thể và với LINQ để Thực thể sử dụng các tính năng mà ngôn ngữ và khung cung cấp cho bạn:

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

@vaheeds Tôi không hiểu câu hỏi đó. Cả hai đều là các ORM khác nhau.
CodeCaster

Xin lỗi, tôi đang tìm kiếm để so sánh hiệu suất của dapper với các ORM khác và tôi đến đây bằng google, vì vậy tôi nghĩ rằng PrintResults(query)truy vấn được tạo sau đó sẽ sử dụng trong dapper làm truy vấn !!
vaheeds

@vaheeds được rồi, nhưng không hiểu câu trả lời không đảm bảo phản đối. Nếu đó là bạn, tình cờ xảy ra cùng lúc với nhận xét của bạn.
CodeCaster

quyền của bạn, đó là một sự hiểu lầm. Tôi bị linq đối với các thực thể hiệu suất kém trên các truy vấn phức tạp. Tôi bù phiếu xuống bởi câu trả lời khác của bạn lên bỏ phiếu;)
vaheeds

Đó không phải là một câu trả lời cho câu hỏi
HGMamaci

17

Một chút quá mức cần thiết trong trường hợp đơn giản này nhưng tôi đã sử dụng mã tương tự như thế này trong quá khứ.

Tạo một chức năng

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

Sử dụng nó như thế này

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

Bằng cách này nếu không có điều kiện nào được tìm thấy, bạn thậm chí không cần tải câu lệnh where trong truy vấn và lưu máy chủ sql một giây để xử lý mệnh đề junk where khi nó phân tích câu lệnh sql.


Tôi không thấy làm thế nào điều này làm cho nó thanh lịch hơn. Nó chắc chắn là không rõ ràng hơn những gì đang xảy ra ở đây. Tôi có thể thấy việc sử dụng chức năng tiện ích đó, nhưng nó không phải là trang nhã hơn.
usr

đưa cho bạn một phiếu bầu cho giác ngộ chúng tôi về tầm quan trọng của một micro giây
user1451111

15

Có một giải pháp khác, cũng có thể không thanh lịch, nhưng hiệu quả và giải quyết được vấn đề:

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

Đối với:

  • danh sách điều kiện trống, kết quả sẽ đơn giản là SELECT * FROM Table1,
  • một điều kiện duy nhất nó sẽ là SELECT * FROM Table1 WHERE cond1
  • mỗi điều kiện sau sẽ tạo thêm AND condN

6
Điều đó để lại một sự lủng lẳng WHEREnếu không có vị ngữ; 1 = 1 tồn tại đặc biệt để tránh điều đó.
Gaius

Vì vậy, chuyển sang String query = "SELECT * FROM Table1";string jointer = " WHERE ";?
Brendan Dài

@BrendanLong Sau đó, WHEREcác ANDs được đặt giữa các điều kiện?
PenguinCoder

@PenguinCoder Thật khó để hiển thị toàn bộ mã trong một nhận xét. Ý tôi là thay thế string joinerdòng bằng string joiner = " WHERE ";, và để nguyên joiner = " AND ";dòng.
Brendan Dài

@Gaius Tôi đã giả định các điều khoản không trống, nhưng đặt WHERE trong trình kết hợp sẽ thực hiện được mẹo. Cảm ơn đã nhận xét!
Dariusz

11

Chỉ cần làm điều gì đó như sau:

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

Nó là SQL injection an toànIMHO , nó khá sạch sẽ. Đơn Remove()giản là loại bỏ cuối cùngAND ;

Nó hoạt động cả nếu không có điều kiện nào được đặt, nếu một điều kiện đã được đặt hoặc nếu nhiều điều kiện đã được đặt.


1
Tôi không chắc chắn (không sử dụng C # bản thân mình) nhưng tôi muốn nói rằng conditions != nullluôn luôn là true, khi bạn khởi tạo nó với ""(trừ khi trong C # "" == null). Nó có lẽ nên là một séc, nếu conditionskhông có sản phẩm nào… ;-)
siegi

9

Chỉ cần nối hai dòng ở phía sau.

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

Ví dụ

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

sẽ trở thành

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

Trong khi

SELECT * FROM Table1 WHERE 1=1 

sẽ trở thành

SELECT * FROM Table1

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

Cảm ơn bạn đã chỉ ra một lỗ hổng của giải pháp này:

"Điều này có thể phá vỡ truy vấn nếu, vì bất kỳ lý do gì, một trong các điều kiện chứa văn bản" 1 = 1 AND "hoặc" WHERE 1 = 1 ". Đây có thể là trường hợp nếu điều kiện chứa truy vấn con hoặc cố gắng kiểm tra xem một số chẳng hạn như cột chứa văn bản này. Có thể đây không phải là vấn đề trong trường hợp của bạn nhưng bạn nên lưu ý… "

Để loại bỏ vấn đề này, chúng ta cần phân biệt WHERE "chính" 1 = 1 và những truy vấn từ truy vấn phụ, điều này thật dễ dàng:

Chỉ cần làm cho WHERE "chính" trở nên đặc biệt: Tôi sẽ thêm một dấu "$"

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

Sau đó, vẫn nối hai dòng:

Query.Replace("WHERE$ 1=1 AND ", "WHERE ");
Query.Replace(" WHERE$ 1=1 ", "");

1
Điều này có thể phá vỡ truy vấn nếu, vì bất kỳ lý do gì, một trong các điều kiện chứa văn bản "1=1 AND "hoặc " WHERE 1=1 ". Đây có thể là trường hợp nếu điều kiện chứa một truy vấn con hoặc cố gắng kiểm tra xem một số cột có chứa văn bản này không, chẳng hạn. Có thể đây không phải là vấn đề trong trường hợp của bạn nhưng bạn nên ghi nhớ…
siegi

8

Dùng cái này:

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

Câu trả lời này sẽ hoạt động và thực sự không có gì sai với nó, nhưng tôi không nghĩ nó ràng và đơn giản hơn câu hỏi ban đầu. Theo tôi, tìm kiếm theo chuỗi QuerySubkhông tốt hơn hay tệ hơn việc sử dụng where 1=1hack. Nhưng đó là một đóng góp đáng suy nghĩ.
catfood

3
Có một lỗi. Đã sửa nó. Truy vấn của tôi sẽ bị đánh bom nếu không có điều kiện nào: - P Vẫn phải nói rằng đối với tôi của Ahmed hoặc CodeCaster là giải pháp tốt nhất. Tôi chỉ trình bày một giải pháp thay thế cho các bạn!
Anshuman

Điều này vẫn sai, nói chung. Giả sử nó là ... FROM SOMETABLE WHERE ; sau đó TrimEndthực sự sẽ giảm điều này xuống ... FROM SOMETABL. Nếu đây thực sự là một StringBuilder(điều này nên xảy ra nếu bạn có nhiều thao tác với chuỗi này hoặc hơn thế nữa) thì bạn có thể chỉ cần Query.Length -= "WHERE ".Length;.
Mark Hurd

Đánh dấu, nó hoạt động. Tôi đã thử điều này trong nhiều dự án. Hãy thử nó và bạn sẽ thấy rằng nó có!
Anshuman

8
xấu xí như địa ngục :) cộng với nó có thể tạo tối đa 7 chuỗi nếu tôi tính một cách chính xác
Piotr Perak

5

Tại sao không sử dụng Trình tạo truy vấn hiện có? Một cái gì đó giống như Sql Kata .

Nó hỗ trợ các điều kiện phức tạp, kết nối và truy vấn con.

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

nó hoạt động với Sql Server, MySql và PostgreSql.


4

Giải pháp nhanh nhất theo nghĩa đen cho những gì bạn đang hỏi mà tôi có thể nghĩ ra là:

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

Nó có vẻ không thanh lịch, chắc chắn, mà tôi sẽ giới thiệu bạn với khuyến nghị của CodeCaster về việc sử dụng ORM. Nhưng nếu bạn nghĩ về những gì điều này đang làm ở đây, bạn thực sự không lo lắng về việc 'lãng phí' 4 ký tự bộ nhớ, và việc máy tính di chuyển con trỏ đến 4 vị trí thực sự nhanh chóng.

Nếu bạn có thời gian để học cách sử dụng ORM, nó thực sự có thể mang lại lợi ích cho bạn. Nhưng liên quan đến điều này, nếu bạn đang cố gắng giữ cho điều kiện bổ sung đó không đánh vào db SQL, điều này sẽ giúp bạn.


4

Nếu đây là SQL Server , bạn có thể làm cho mã này sạch hơn nhiều.

Điều này cũng giả định một số lượng tham số đã biết, có thể là một giả định kém khi tôi nghĩ về các khả năng.

Trong C #, bạn sẽ sử dụng:

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

Và sau đó về phía 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

Ẩn các cột của bạn bên trong một biểu thức có thể ngăn cản việc sử dụng các chỉ mục và kỹ thuật này không được khuyến khích vì lý do này ở đây .
bbsimonbb

đó là một phát hiện thú vị. Cảm ơn vì thông tin đó. sẽ cập nhật
mckeejm

3

Tùy thuộc vào điều kiện, có thể sử dụng logic boolean trong truy vấn. Một cái gì đó như thế này:

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

3

Tôi thích giao diện thông thạo của stringbuilder, vì vậy tôi đã tạo một số 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;
}

2

IMHO, tôi nghĩ rằng cách tiếp cận của bạn là sai:

Truy vấn cơ sở dữ liệu bằng cách nối chuỗi KHÔNG BAO GIỜ là một ý tưởng hay (nguy cơ tiêm SQL và mã có thể dễ dàng bị hỏng nếu bạn thực hiện một số thay đổi ở nơi khác).

Bạn có thể sử dụng ORM (tôi sử dụng NHibernate ) hoặc ít nhất là sử dụngSqlCommand.Parameters

Nếu bạn thực sự muốn sử dụng nối chuỗi, tôi sẽ sử dụng a StringBuilder(nó là đối tượng phù hợp để nối chuỗi):

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;

Như suy nghĩ cuối cùng, Where 1=1nó thực sự xấu xí nhưng SQL Server sẽ tối ưu hóa nó.


SELECT * FROM Table1 WHERE AND Col1=0có vẻ không đúng, đó là toàn bộ điểm của WHERE 1=1.
Mormegil

2

Dapper SqlBuilder là một lựa chọn khá tốt. Nó thậm chí còn được sử dụng trong sản xuất trên StackOverflow.

Đọc mục blog của Sam về nó .

Theo như tôi biết, nó không phải là một phần của bất kỳ gói Nuget nào, vì vậy bạn sẽ cần sao chép, dán mã của nó vào dự án của mình hoặc tải xuống nguồn Dapper và xây dựng dự án SqlBuilder. Dù bằng cách nào, bạn cũng sẽ cần tham chiếu Dapper cho DynamicParameterslớp.


1
Tôi không nghĩ rằng Dapper's SqlBuilder được bao gồm trong gói đó.
Ronnie Overby

1

Tôi thấy điều này được sử dụng mọi lúc trong Oracle khi xây dựng SQL động trong các thủ tục được lưu trữ . Tôi sử dụng nó trong các truy vấn trong khi khám phá các vấn đề dữ liệu cũng như chỉ để chuyển đổi giữa các bộ lọc dữ liệu khác nhau nhanh hơn ... Chỉ cần nhận xét một điều kiện hoặc thêm lại điều kiện một cách dễ dàng.

Tôi thấy nó khá phổ biến và đủ dễ hiểu để ai đó xem xét mã của bạn.


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

Hiện thực hóa bằng các phương pháp mở rộng.

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

ĐI CHỐNG LẠI!
Ronnie Overby

Thực thi tôi? Du nghĩa là gì?
Maxim Zhukov

0

Sử dụng stringhàm, bạn cũng có thể thực hiện theo cách này:

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  

Cá nhân tôi cảm thấy dễ dàng loại bỏ (các) phần tử điều kiện ở cuối, vì vị trí của nó rất dễ đoán.


0

Tôi đã nghĩ ra một giải pháp mà, tốt, có lẽ là dễ đọc hơn:

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

Tôi chỉ không chắc liệu trình thông dịch SQL cũng sẽ tối ưu hóa Col1 = Col1điều kiện (được in khi condition1là sai).


0

Đây là một cách thanh lịch hơn:

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

0

Như đã nói, tạo SQL bằng cách nối không bao giờ là một ý tưởng hay . Không chỉ vì SQL injection. Chủ yếu là vì nó xấu xí, khó bảo trì và hoàn toàn không cần thiết . Bạn phải chạy chương trình của mình với dấu vết hoặc gỡ lỗi để xem nó tạo ra SQL nào. Nếu bạn sử dụng QueryFirst (tuyên bố từ chối trách nhiệm: mà tôi đã viết), sự cám dỗ không vui sẽ bị loại bỏ và bạn có thể thực hiện ngay trong SQL.

Trang này có phạm vi toàn diện về các tùy chọn TSQL để thêm động từ tìm kiếm. Tùy chọn sau đây rất hữu ích cho các trường hợp bạn muốn để lại lựa chọn kết hợp các vị từ tìm kiếm cho người dùng của mình.

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 cung cấp cho bạn C # null đến db NULL, vì vậy bạn chỉ cần gọi phương thức Execute () với null khi thích hợp và tất cả đều hoạt động. <opinion> Tại sao các nhà phát triển C # lại miễn cưỡng làm những thứ trong SQL, ngay cả khi nó đơn giản hơn. Tâm trí khó hiểu. </opinion>


0

Đối với các bước lọc dài hơn, StringBuilder là cách tiếp cận tốt hơn như nhiều người nói.

trong trường hợp của bạn, tôi sẽ đi với:

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 "

0

Cô đọng, thanh lịch và ngọt ngào, như thể hiện trong hình ảnh dưới đây.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.