Tại sao ai đó sẽ sử dụng WHERE 1 = 1 AND <condition> trong mệnh đề SQL?


257

Tại sao ai đó sẽ sử dụng WHERE 1=1 AND <conditions>trong mệnh đề SQL (Hoặc SQL có được thông qua các chuỗi được nối, hoặc là định nghĩa chế độ xem)

Tôi đã thấy ở đâu đó rằng điều này sẽ được sử dụng để bảo vệ chống lại SQL Injection, nhưng nó có vẻ rất kỳ lạ.

Nếu có tiêm WHERE 1 = 1 AND injected OR 1=1sẽ có kết quả tương tự injected OR 1=1.

Chỉnh sửa sau: Điều gì về việc sử dụng trong một định nghĩa xem?


Cảm ơn bạn cho câu trả lời của bạn.

Tuy nhiên, tôi không hiểu tại sao ai đó sẽ sử dụng cấu trúc này để xác định chế độ xem hoặc sử dụng nó trong một thủ tục được lưu trữ.

Lấy ví dụ này:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value

3
"Tại sao ai đó sẽ sử dụng cấu trúc này để xác định chế độ xem" Có lẽ là do thói quen. Nó cung cấp không có lợi thế chức năng trong các truy vấn tĩnh.
ADTC

Câu trả lời:


346

Nếu danh sách các điều kiện không được biết đến vào thời gian biên dịch và thay vào đó được xây dựng vào thời gian chạy, bạn không phải lo lắng về việc bạn có một hay nhiều điều kiện hay không. Bạn có thể tạo tất cả chúng như:

and <condition>

và nối tất cả chúng lại với nhau. Khi 1=1bắt đầu, ban đầuand có một cái gì đó để liên kết.

Tôi chưa bao giờ thấy điều này được sử dụng cho bất kỳ loại bảo vệ tiêm nào, như bạn nói nó dường như không giúp được gì nhiều. Tôi đã thấy nó được sử dụng như là một thuận tiện thực hiện. Công cụ truy vấn SQL cuối cùng sẽ bỏ qua 1=1vì vậy nó sẽ không có tác động hiệu suất.


34
Đôi khi không phải là lười biếng, nhưng có một mã sạch hơn.
Eduardo Molteni

39
đối phó với các AND và COMMA theo dõi không bẩn ... không có gì sạch hơn bằng cách có 1 = 1 trên toàn bộ SQL của bạn.

21
DBA? Họ để làm gì? :)
Eduardo Molteni

38
DBA đang có mặt để dọn dẹp sau khi các lập trình viên nghĩ rằng họ biết cách sử dụng cơ sở dữ liệu một cách hiệu quả.
Adrian Pronk

23
"Lười" Tôi thích nghĩ rằng nó thông minh, không lười biếng. Bạn đang tránh mã lặp đi lặp lại và kiểm tra điều kiện không cần thiết. Không thể thêm where 1=1(Oracle) hoặc where true(Postgres), tôi sẽ phải kiểm tra từng điều kiện cho dù đó là điều kiện đầu tiên. Không có điểm nào trong việc làm như vậy, và nó chỉ thêm nhiều mã soạn sẵn.
ADTC

113

Chỉ cần thêm một mã ví dụ vào câu trả lời của Greg:

dim sqlstmt as new StringBuilder
sqlstmt.add("SELECT * FROM Products")
sqlstmt.add(" WHERE 1=1") 

''// From now on you don't have to worry if you must 
''// append AND or WHERE because you know the WHERE is there
If ProductCategoryID <> 0 then
  sqlstmt.AppendFormat(" AND ProductCategoryID = {0}", trim(ProductCategoryID))
end if
If MinimunPrice > 0 then
  sqlstmt.AppendFormat(" AND Price >= {0}", trim(MinimunPrice))
end if

6
bit hacky, nhưng có vẻ như là một sử dụng hợp lệ.
Mike

5
Đây phải là câu trả lời được chấp nhận. Việc thực hành chỉ thực sự là hack xung quanh để không phải xác định bạn có bao nhiêu điều kiện.
aglassman

38

Tôi đã thấy nó được sử dụng khi số lượng điều kiện có thể thay đổi.

Bạn có thể nối các điều kiện bằng chuỗi "VÀ". Sau đó, thay vì đếm số điều kiện bạn đang chuyển đến, bạn đặt "WHERE 1 = 1" vào cuối câu lệnh SQL chứng khoán của bạn và đưa ra các điều kiện được nối.

Về cơ bản, nó giúp bạn tiết kiệm phải thực hiện kiểm tra các điều kiện và sau đó thêm chuỗi "WHERE" trước chúng.


28

Có vẻ như một cách lười biếng để luôn biết rằng mệnh đề WHERE của bạn đã được xác định và cho phép bạn tiếp tục thêm các điều kiện mà không phải kiểm tra xem đó có phải là điều khoản đầu tiên không.


12
"Lười" Tôi thích nghĩ rằng nó thông minh, không lười biếng. Bạn đang tránh mã lặp đi lặp lại và kiểm tra điều kiện không cần thiết. Không thể thêm where 1=1(Oracle) hoặc where true(Postgres), tôi sẽ phải kiểm tra từng điều kiện cho dù đó là điều kiện đầu tiên. Không có điểm nào trong việc làm như vậy, và nó chỉ thêm nhiều mã soạn sẵn.
ADTC

2
@ADTC Viết mã thường - nếu không chủ yếu - về việc xử lý các điều kiện khác nhau. Đây chỉ là một điều kiện khác cần được xử lý, mà cá nhân tôi nghĩ là lười làm ô nhiễm SQL được tạo ra. Nếu bạn thiết kế mã của mình để thêm 'Trường hợp 1 = 1' ở MỘT vị trí, bạn có thể - với một chút nỗ lực - xử lý sự khác biệt giữa số không và nhiều điều kiện trong MỘT vị trí đó trong mã của bạn. Tôi đoán là mặc dù, những người ủng hộ cho 'Trường hợp 1 = 1' rắc nó trên khắp cơ sở mã của họ, điều này đưa tôi đến kết luận về sự lười biếng sinh ra sự lười biếng.
Jason S

@JasonS Laziness là cha đẻ của Sáng chế.
ADTC

@ADTC Tôi lười biếng vì tôi không muốn cập nhật mã ở hàng trăm nơi, vì vậy phát minh được đặt ở một nơi. Đối với tôi WHERE 1=1, công việc bổ sung là duy trì cùng một mã ở nhiều nơi và đọc nó trong tất cả SQL được tạo của bạn. Tôi lười hơn bạn nghĩ!
Jason S

19

Liên quan gián tiếp: khi 1 = 2 được sử dụng:

CREATE TABLE New_table_name 
as 
select * 
FROM Old_table_name 
WHERE 1 = 2;

điều này sẽ tạo ra một bảng mới với cùng một lược đồ như bảng cũ. (Rất tiện dụng nếu bạn muốn tải một số dữ liệu để so sánh)


3
Quên thêm, trong khi nó sẽ tạo một bảng mới có cùng dữ liệu như cũ, bảng mới sẽ không có các ràng buộc khác như khóa ngoại từ bảng cũ
15:51

16

Biểu thức 1 = 1 thường được sử dụng trong mã sql được tạo. Biểu thức này có thể đơn giản hóa mã tạo sql làm giảm số lượng câu lệnh điều kiện.


11

Trên thực tế, tôi đã thấy loại điều này được sử dụng trong các báo cáo BIRT. Truy vấn được truyền cho thời gian chạy BIRT có dạng:

select a,b,c from t where a = ?

và '?' được thay thế trong thời gian chạy bằng một giá trị tham số thực tế được chọn từ hộp thả xuống. Các lựa chọn trong trình đơn thả xuống được đưa ra bởi:

select distinct a from t
union all
select '*' from sysibm.sysdummy1

để bạn có được tất cả các giá trị có thể cộng với " *". Nếu người dùng chọn " *" từ hộp thả xuống (có nghĩa là tất cả các giá trị của một nên được chọn), truy vấn phải được sửa đổi (bằng Javascript) trước khi được chạy.

Kể từ "?" là một tham số vị trí và PHẢI vẫn ở đó để những thứ khác hoạt động, Javascript sửa đổi truy vấn thành:

select a,b,c from t where ((a = ?) or (1==1))

Điều đó về cơ bản loại bỏ ảnh hưởng của mệnh đề where trong khi vẫn giữ nguyên tham số vị trí.

Tôi cũng đã thấy trường hợp AND được sử dụng bởi các lập trình viên lười biếng trong khi tự động tạo một truy vấn SQL.

Giả sử bạn phải tự động tạo một truy vấn bắt đầu bằng select * from tvà kiểm tra:

  • tên là Bob; và
  • mức lương> $ 20.000

một số người sẽ thêm cái đầu tiên bằng WHERE và những cái tiếp theo với AND do đó:

select * from t where name = 'Bob' and salary > 20000

Các lập trình viên lười biếng (và đó không nhất thiết là một đặc điểm xấu ) sẽ không phân biệt giữa các điều kiện được thêm vào, họ sẽ bắt đầu select * from t where 1=1và chỉ thêm các mệnh đề AND sau đó.

select * from t where 1=1 and name = 'Bob' and salary > 20000

1
"Lười" Tôi thích nghĩ rằng nó thông minh, không lười biếng. Bạn đang tránh mã lặp đi lặp lại và kiểm tra điều kiện không cần thiết. Không thể thêm where 1=1(Oracle) hoặc where true(Postgres), tôi sẽ phải kiểm tra từng điều kiện cho dù đó là điều kiện đầu tiên. Không có điểm nào trong việc làm như vậy, và nó chỉ thêm nhiều mã soạn sẵn.
ADTC

1
@ADTC, ý tôi không phải là lười biếng. Trong thực tế, lười biếng là một đặc điểm tốt trong lập trình :-) Tôi sẽ làm rõ.
paxdiablo

Sự lười biếng là gốc rễ của mọi tội lỗi
Ivanzinho

11

Tôi đã tìm thấy mẫu này hữu ích khi tôi đang thử nghiệm hoặc kiểm tra lại mọi thứ trên cơ sở dữ liệu, vì vậy tôi có thể nhận xét rất nhanh các điều kiện khác:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
AND Table.Field=Value
AND Table.IsValid=true

trở thành:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value
--AND Table.IsValid=true

10

trong đó 1 = 0, Điều này được thực hiện để kiểm tra xem bảng có tồn tại không. Không biết tại sao 1 = 1 được sử dụng.


1
Nhìn thấy điều này được sử dụng để trả về một tập kết quả trống từ cơ sở dữ liệu sẽ được sử dụng như một người giữ cho các bản ghi mới.
Gary Kindel

6

Mặc dù tôi có thể thấy rằng 1 = 1 sẽ hữu ích cho SQL được tạo, một kỹ thuật tôi sử dụng trong PHP là tạo ra một mảng các mệnh đề và sau đó làm

implode (" AND ", $clauses);

do đó tránh được vấn đề có AND dẫn đầu hoặc trailing. Rõ ràng điều này chỉ hữu ích nếu bạn biết rằng bạn sẽ có ít nhất một điều khoản!


1
Đó là nơi 1 = 1 xuất hiện. Nó cung cấp cho bạn rằng "ít nhất một mệnh đề" để bạn không phải lo lắng về việc chỉ cần vỗ vào "VÀ abc"
Carl

Tôi thích ý tưởng này! Xem ở đây để biết ví dụ đầy đủ hơn stackoverflow.com/questions353326160/ từ
drooh

5

Đây là một ví dụ có liên quan chặt chẽ: sử dụng câu lệnh SQL MERGEđể cập nhật mục tiêu được gắn thẻ bằng cách sử dụng tất cả các giá trị từ bảng nguồn nơi không có thuộc tính chung nào để tham gia vào, ví dụ:

MERGE INTO Circles
   USING 
      (
        SELECT pi
         FROM Constants
      ) AS SourceTable
   ON 1 = 1
WHEN MATCHED THEN 
  UPDATE
     SET circumference = 2 * SourceTable.pi * radius;

5

Tại sao ai đó sẽ sử dụng WHERE 1 = 1 VÀ <proper conditions>

Tôi đã thấy các khung công việc tại nhà làm những việc như thế này ( đỏ mặt ), vì điều này cho phép các thực hành phân tích cú pháp lười biếng được áp dụng cho cả từ khóa WHEREANDSql.

Ví dụ: (tôi đang sử dụng C # làm ví dụ ở đây), hãy xem xét phân tích cú pháp có điều kiện của các vị từ sau trong truy vấn Sql string builder:

var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1"
if (shouldFilterForBars)
{
    sqlQuery = sqlQuery + " AND Bars > 3";
}
if (shouldFilterForBaz)
{
    sqlQuery = sqlQuery + " AND Baz < 12";
}

"Lợi ích" của WHERE 1 = 1phương tiện là không cần mã đặc biệt:

  • Đối với AND - cho dù không, một hoặc cả hai vị từ (Bars và Baz) nên được áp dụng, điều này sẽ xác định xem đầu tiên ANDcó được yêu cầu hay không. Vì chúng ta đã có ít nhất một vị từ với 1 = 1, điều đó có nghĩa ANDlà luôn ổn.
  • Không có vị từ nào cả - Trong trường hợp có các vị từ ZERO, thì WHEREphải bỏ đi. Nhưng một lần nữa, chúng ta có thể lười biếng, bởi vì chúng ta một lần nữa đảm bảo ít nhất một vị ngữ.

Đây rõ ràng là một ý tưởng tồi và sẽ khuyên bạn nên sử dụng khung truy cập dữ liệu đã được thiết lập hoặc ORM để phân tích các vị từ tùy chọn và điều kiện theo cách này.


Hoặc nếu tự lăn, trình xây dựng mệnh đề where phải ở một nơi trong mã của bạn. Sau đó, bạn có thể xử lý các vị từ 0 hoặc nhiều hơn các vị từ 0 trong một vị trí trong mã của bạn. Sự nghi ngờ của tôi là sự tồn tại của WHERE 1=1một chỉ báo công bằng KHÔNG phải là trường hợp đó, rằng cơ sở mã bị lấp đầy bởi các chuỗi của chuỗi WHERE 1=1, điều này sẽ chỉ ra cho tôi một vấn đề về kiến ​​trúc ứng dụng và tôi đoán không phải là vấn đề duy nhất!
Jason S

1
Trên thực tế không có gì "xấu" về ý tưởng, ít hơn một lỗi "rõ ràng". Cũng không phải là một ORM một cách thích hợp trong mọi trường hợp. Tìm hiểu SQL và người đại số quan hệ ...
Hejazzman

4

Nếu bạn đến đây để tìm kiếm WHERE 1, lưu ý rằng WHERE 1WHERE 1=1giống hệt nhau. WHERE 1được sử dụng hiếm khi bởi vì một số hệ thống cơ sở dữ liệu từ chối nó xem xét WHERE 1không thực sự là boolean.


2

Điều này rất hữu ích trong trường hợp bạn phải sử dụng truy vấn động trong đó mệnh đề bạn phải nối thêm một số tùy chọn bộ lọc. Giống như nếu bạn bao gồm các tùy chọn 0 cho trạng thái không hoạt động, 1 cho hoạt động. Dựa trên các tùy chọn, chỉ có hai tùy chọn khả dụng (0 và 1) nhưng nếu bạn muốn hiển thị Tất cả các bản ghi, sẽ rất hữu ích khi đưa vào vị trí đóng 1 = 1. Xem mẫu dưới đây:

Declare @SearchValue    varchar(8) 
Declare @SQLQuery varchar(max) = '
Select [FirstName]
    ,[LastName]
    ,[MiddleName]
    ,[BirthDate]
,Case
    when [Status] = 0 then ''Inactive''
    when [Status] = 1 then ''Active''
end as [Status]'

Declare @SearchOption nvarchar(100)
If (@SearchValue = 'Active')
Begin
    Set @SearchOption = ' Where a.[Status] = 1'
End

If (@SearchValue = 'Inactive')
Begin
    Set @SearchOption = ' Where a.[Status] = 0'
End

If (@SearchValue = 'All')
Begin
    Set @SearchOption = ' Where 1=1'
End

Set @SQLQuery = @SQLQuery + @SearchOption

Exec(@SQLQuery);

2

Sau khi xem xét tất cả các câu trả lời, tôi quyết định thực hiện một số thử nghiệm như

SELECT
*
FROM MyTable

WHERE 1=1

Sau đó tôi kiểm tra với các số khác

WHERE 2=2
WHERE 10=10
WHERE 99=99

ect Đã thực hiện tất cả các kiểm tra, thị trấn chạy truy vấn là như nhau. thậm chí không có mệnh đề where. Tôi không phải là một fan hâm mộ của cú pháp


1

Tôi thường làm điều này khi tôi đang xây dựng SQL động cho một báo cáo có nhiều giá trị thả xuống mà người dùng có thể chọn. Vì người dùng có thể hoặc không thể chọn các giá trị từ mỗi lần thả xuống, nên cuối cùng chúng tôi sẽ gặp khó khăn trong việc tìm ra điều kiện nào là mệnh đề where đầu tiên. Vì vậy, chúng tôi đưa ra truy vấn where 1=1cuối cùng và thêm tất cả các mệnh đề sau đó.

Cái gì đó như

select column1, column2 from my table where 1=1 {name} {age};

Sau đó, chúng tôi sẽ xây dựng mệnh đề where như thế này và chuyển nó dưới dạng giá trị tham số

string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : "";

Vì lựa chọn mệnh đề mà chúng ta không biết trong thời gian chạy, vì vậy điều này giúp chúng ta rất nhiều trong việc tìm kiếm có bao gồm một 'AND' or 'WHERE'.


0

Sử dụng một vị từ như 1=1là một gợi ý bình thường đôi khi được sử dụng để buộc kế hoạch truy cập sử dụng hoặc không sử dụng quét chỉ mục. Lý do tại sao điều này được sử dụng là khi bạn đang sử dụng truy vấn được nối nhiều tổ với nhiều biến vị ngữ trong mệnh đề where trong đó đôi khi thậm chí sử dụng tất cả các chỉ mục khiến kế hoạch truy cập đọc từng bảng - quét toàn bộ bảng. Đây chỉ là 1 trong nhiều gợi ý được các DBA sử dụng để lừa một dbms sử dụng đường dẫn hiệu quả hơn. Đừng ném một cái vào; bạn cần một dba để phân tích truy vấn vì nó không luôn hoạt động.


4
Bạn có bất kỳ trích dẫn nào ghi lại hành vi này cho một số cơ sở dữ liệu không?
Joe

0

Đây là trường hợp sử dụng ... tuy nhiên tôi không quá quan tâm đến các kỹ thuật tại sao tôi nên hay không sử dụng 1 = 1. Tôi đang viết một hàm, sử dụng pyodbc để lấy một số dữ liệu từ SQL Server. Tôi đang tìm cách để buộc một filler sau wheretừ khóa trong mã của tôi. Đây thực sự là một gợi ý tuyệt vời:

if _where == '': _where = '1=1'
...
...
...
cur.execute(f'select {predicate} from {table_name} where {_where}')

Lý do là vì tôi không thể thực hiện từ khóa 'where' cùng nhau bên trong biến mệnh đề _where. Vì vậy, tôi nghĩ rằng việc sử dụng bất kỳ điều kiện giả nào được đánh giá là đúng sẽ làm như một phụ.


-1

Lần đầu tiên tôi bắt gặp điều này trở lại với ADO và asp cổ điển, câu trả lời tôi nhận được là: hiệu suất. nếu bạn làm thẳng

Select * from tablename

và vượt qua nó như là một lệnh / văn bản sql, bạn sẽ có được sự gia tăng hiệu suất đáng chú ý với

Where 1=1

thêm vào, đó là một sự khác biệt có thể nhìn thấy. một cái gì đó để làm với các tiêu đề bảng được trả lại ngay khi điều kiện đầu tiên được đáp ứng, hoặc một số điều điên rồ khác, dù sao, nó đã tăng tốc mọi thứ.


3
Nếu đó là sự thật, tại sao DBMS không luôn luôn thêm điều đó?
Carcamano

5
Bạn có thể đưa ra bằng chứng?
Peter G.
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.