Mengapa seseorang menggunakan WHERE 1 = 1 DAN <conditions> dalam klausa SQL?

257

Mengapa seseorang akan menggunakan WHERE 1=1 AND <conditions>klausa SQL (Entah SQL diperoleh melalui string gabungan, baik definisi tampilan)

Saya telah melihat di suatu tempat bahwa ini akan digunakan untuk melindungi terhadap SQL Injection, tetapi tampaknya sangat aneh.

Jika ada injeksi WHERE 1 = 1 AND injected OR 1=1akan memiliki hasil yang sama dengan injected OR 1=1.

Sunting nanti: Bagaimana dengan penggunaan dalam definisi tampilan?


Terima kasih atas jawaban anda

Namun, saya tidak mengerti mengapa seseorang menggunakan konstruksi ini untuk mendefinisikan tampilan, atau menggunakannya dalam prosedur tersimpan.

Ambil ini sebagai contoh:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Bogdan Maxim
sumber
3
"Mengapa seseorang menggunakan konstruksi ini untuk mendefinisikan pandangan" Mungkin karena kebiasaan. Ini tidak menawarkan keuntungan fungsional dalam permintaan statis.
ADTC

Jawaban:

346

Jika daftar kondisi tidak diketahui pada waktu kompilasi dan sebagai gantinya dibangun pada waktu berjalan, Anda tidak perlu khawatir apakah Anda memiliki satu atau lebih dari satu kondisi. Anda dapat menghasilkan semuanya seperti:

and <condition>

dan menyatukan semuanya. Dengan 1=1di awal, inisial andmemiliki sesuatu untuk dikaitkan.

Saya belum pernah melihat ini digunakan untuk segala jenis perlindungan injeksi, seperti yang Anda katakan sepertinya tidak akan banyak membantu. Saya telah melihatnya digunakan sebagai kenyamanan implementasi. Mesin query SQL pada akhirnya akan mengabaikan 1=1sehingga seharusnya tidak memiliki dampak kinerja.

Greg Hewgill
sumber
34
Terkadang bukan tentang menjadi malas, tetapi memiliki kode yang lebih bersih.
Eduardo Molteni
39
berurusan dengan trailing ANDs atau COMMA tidak kotor ... tidak ada yang lebih bersih dengan memiliki 1 = 1 di seluruh SQL Anda.
21
DBA? Untuk apa mereka? :)
Eduardo Molteni
38
DBA ada untuk membersihkan setelah programmer yang berpikir mereka tahu cara menggunakan database secara efektif.
Adrian Pronk
23
"Malas" Aku suka berpikir itu pintar, tidak malas. Anda menghindari kode berulang dan pemeriksaan kondisi yang tidak perlu. Tanpa bisa menambahkan where 1=1(Oracle) atau where true(Postgres), saya harus memeriksa setiap kondisi apakah itu yang pertama. Tidak ada gunanya melakukannya, dan itu hanya menambah kode boilerplate.
ADTC
113

Hanya menambahkan kode contoh ke jawaban 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
Eduardo Molteni
sumber
6
agak hacky, tetapi sepertinya penggunaan yang valid.
Mike
5
Ini harus menjadi jawaban yang diterima. Latihan ini sebenarnya hanya peretasan untuk tidak harus menentukan berapa banyak persyaratan yang Anda miliki.
Aglassman
38

Saya pernah melihatnya digunakan ketika jumlah kondisi dapat bervariasi.

Anda dapat menggabungkan kondisi menggunakan string "DAN". Kemudian, alih-alih menghitung jumlah kondisi yang Anda lewati, Anda menempatkan "WHERE 1 = 1" di akhir pernyataan SQL stok Anda dan melemparkan pada kondisi gabungan.

Pada dasarnya, ini menghemat Anda harus melakukan tes untuk kondisi dan kemudian menambahkan string "DI MANA" sebelum mereka.

Carl
sumber
28

Sepertinya cara malas untuk selalu tahu bahwa klausa WHERE Anda sudah ditentukan dan memungkinkan Anda untuk terus menambahkan kondisi tanpa harus memeriksa apakah itu yang pertama.

John Lemp
sumber
12
"Malas" Aku suka berpikir itu pintar, tidak malas. Anda menghindari kode berulang dan pemeriksaan kondisi yang tidak perlu. Tanpa bisa menambahkan where 1=1(Oracle) atau where true(Postgres), saya harus memeriksa setiap kondisi apakah itu yang pertama. Tidak ada gunanya melakukannya, dan itu hanya menambah kode boilerplate.
ADTC
2
@ADTC Menulis kode sering - jika tidak sebagian besar - tentang menangani kondisi yang berbeda. Ini hanyalah kondisi lain yang perlu ditangani, yang menurut saya pribadi malas mencemari SQL yang dihasilkan. Jika Anda membuat kode untuk menambahkan 'Di mana 1 = 1' di SATU tempat, Anda bisa - dengan sedikit usaha ekstra - menangani perbedaan antara nol dan banyak kondisi di SATU tempat itu dalam kode Anda. Dugaan saya adalah, pendukung untuk 'Di mana 1 = 1' menaburkannya di seluruh basis kode mereka, yang membawa saya pada kesimpulan kemalasan menghasilkan kemalasan.
Jason S
@JasonS Laziness adalah bapak Penemuan.
ADTC
@ADTC Saya malas karena saya tidak suka memperbarui kode di ratusan tempat, jadi penemuan ini meletakkannya di satu tempat. Bagi saya WHERE 1=1menghasilkan pekerjaan ekstra menjaga kode yang sama di banyak tempat dan membacanya di semua SQL yang Anda hasilkan. Saya lebih malas dari Anda saya pikir!
Jason S
19

Relevan Tidak Langsung: ketika 1 = 2 digunakan:

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

ini akan membuat tabel baru dengan skema yang sama dengan tabel lama. (Sangat berguna jika Anda ingin memuat beberapa data untuk perbandingan)

milso
sumber
3
Lupa menambahkan, sementara itu akan membuat tabel baru dengan data yang sama dengan yang lama, tabel baru tidak akan memiliki kendala lain seperti kunci asing dari tabel yang lebih tua
milso
16

1 = 1 ekspresi umum digunakan dalam kode sql yang dihasilkan. Ungkapan ini dapat menyederhanakan kode menghasilkan sql mengurangi jumlah pernyataan bersyarat.

aku
sumber
11

Sebenarnya, saya pernah melihat hal semacam ini digunakan dalam laporan BIRT. Kueri yang diteruskan ke runtime BIRT adalah dalam bentuk:

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

dan '?' diganti pada saat runtime oleh nilai parameter aktual yang dipilih dari kotak drop-down. Pilihan dalam drop-down diberikan oleh:

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

sehingga Anda mendapatkan semua nilai yang mungkin plus " *". Jika pengguna memilih " *" dari kotak drop down (artinya semua nilai a harus dipilih), kueri harus dimodifikasi (dengan Javascript) sebelum dijalankan.

Sejak "?" adalah parameter posisi dan HARUS tetap ada untuk hal lain berfungsi, Javascript memodifikasi kueri menjadi:

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

Itu pada dasarnya menghilangkan efek klausa di mana sementara masih meninggalkan parameter posisi di tempatnya.

Saya juga melihat kasus AND yang digunakan oleh lazy coders sementara secara dinamis membuat query SQL.

Katakanlah Anda harus secara dinamis membuat kueri yang dimulai dengan select * from tdan memeriksa:

  • namanya adalah Bob; dan
  • gajinya> $ 20.000

beberapa orang akan menambahkan yang pertama dengan WHERE dan yang berikutnya dengan DAN dengan demikian:

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

Pemrogram malas (dan itu tidak selalu sifat buruk ) tidak akan membedakan antara kondisi yang ditambahkan, mereka akan mulai dengan select * from t where 1=1dan hanya menambahkan klausa DAN setelah itu.

select * from t where 1=1 and name = 'Bob' and salary > 20000
paxdiablo
sumber
1
"Malas" Aku suka berpikir itu pintar, tidak malas. Anda menghindari kode berulang dan pemeriksaan kondisi yang tidak perlu. Tanpa bisa menambahkan where 1=1(Oracle) atau where true(Postgres), saya harus memeriksa setiap kondisi apakah itu yang pertama. Tidak ada gunanya melakukannya, dan itu hanya menambah kode boilerplate.
ADTC
1
@ADTC, saya tidak bermaksud malas dengan cara yang buruk. Sebenarnya, malas adalah sifat yang baik dalam pemrograman :-) Saya akan mengklarifikasi.
paxdiablo
Kemalasan adalah akar dari semua kejahatan
Ivanzinho
11

Saya menemukan berguna pola ini ketika saya sedang menguji atau menggandakan memeriksa hal-hal pada database, jadi saya dapat berkomentar dengan sangat cepat kondisi lain:

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

berubah menjadi:

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

di mana 1 = 0, ini dilakukan untuk memeriksa apakah tabel ada. Tidak tahu mengapa 1 = 1 digunakan.


sumber
1
Terlihat ini digunakan untuk mengembalikan resultset kosong dari database untuk digunakan sebagai pemegang untuk catatan baru.
Gary Kindel
6

Sementara saya bisa melihat bahwa 1 = 1 akan berguna untuk menghasilkan SQL, teknik yang saya gunakan dalam PHP adalah membuat array klausa dan kemudian melakukan

implode (" AND ", $clauses);

dengan demikian menghindari masalah memiliki AND yang memimpin atau tertinggal. Jelas ini hanya berguna jika Anda tahu bahwa Anda akan memiliki setidaknya satu klausa!

sanbikinoraion
sumber
1
Di situlah 1 = 1 masuk. Ini memberi Anda bahwa "setidaknya satu klausa" sehingga Anda tidak perlu khawatir hanya menampar "DAN abc"
Carl
Aku suka ide ini! Lihat di sini untuk contoh yang lebih lengkap stackoverflow.com/questions/35326160/…
drooh
5

Berikut ini adalah contoh terkait: menggunakan MERGEpernyataan SQL untuk memperbarui target yang diajukan dengan menggunakan semua nilai dari tabel sumber di mana tidak ada atribut umum yang digunakan untuk bergabung misalnya

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

Mengapa seseorang menggunakan WHERE 1 = 1 AND <proper conditions>

Saya telah melihat kerangka kerja homespun melakukan hal-hal seperti ini ( blush ), karena ini memungkinkan praktik parsing malas diterapkan pada kata kunci WHEREdan ANDSql.

Misalnya (saya menggunakan C # sebagai contoh di sini), pertimbangkan penguraian bersyarat dari predikat berikut dalam kueri 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";
}

"Manfaat" dari WHERE 1 = 1berarti tidak diperlukan kode khusus:

  • Untuk DAN - apakah nol, satu atau keduanya predikat (Bilah dan Baz) harus diterapkan, yang akan menentukan apakah yang pertama ANDdiperlukan. Karena kita sudah memiliki setidaknya satu predikat dengan 1 = 1, itu berarti ANDselalu baik-baik saja.
  • Tanpa predikat sama sekali - Dalam kasus di mana ada predikat NOL, maka WHEREharus dijatuhkan. Tapi sekali lagi, kita bisa malas, karena kita lagi dijamin paling tidak satu predikat.

Ini jelas merupakan ide yang buruk dan akan merekomendasikan menggunakan kerangka kerja akses data atau ORM yang telah ditetapkan untuk mengurai predikat opsional dan bersyarat dengan cara ini.

StuartLC
sumber
Atau jika menggulirkan milik Anda sendiri, pembuat klausa mana harus berada di satu tempat dalam kode Anda. Kemudian Anda dapat menangani predikat nol atau lebih dari nol predikat di satu lokasi dalam kode Anda. Kecurigaan saya adalah bahwa keberadaan WHERE 1=1indikator yang adil bahwa BUKAN terjadi, bahwa basis kode dipenuhi dengan bit string WHERE 1=1, yang akan menunjukkan kepada saya masalah arsitektur aplikasi, dan saya kira bukan satu-satunya!
Jason S
1
Sebenarnya tidak ada yang "buruk" tentang ide itu, apalagi kesalahan "jelas". ORM juga bukan cara yang tepat untuk semua kasus. Pelajari SQL dan orang-orang Aljabar Relasional ...
Hejazzman
4

Jika Anda datang ke sini untuk mencari WHERE 1, perhatikan itu WHERE 1dan WHERE 1=1identik. WHERE 1jarang digunakan karena beberapa sistem database menolaknya mengingat WHERE 1tidak benar-benar menjadi boolean.

Yogesh Umesh Vaity
sumber
2

Ini berguna dalam kasus di mana Anda harus menggunakan kueri dinamis di mana di mana klausa Anda harus menambahkan beberapa opsi filter. Seperti jika Anda memasukkan opsi 0 untuk status tidak aktif, 1 untuk aktif. Berdasarkan dari opsi, hanya ada dua opsi yang tersedia (0 dan 1) tetapi jika Anda ingin menampilkan Semua catatan, mudah untuk memasukkan di mana dekat 1 = 1. Lihat di bawah sampel:

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);
Eliseo Jr
sumber
2

Setelah meninjau semua jawaban, saya memutuskan untuk melakukan beberapa eksperimen seperti

SELECT
*
FROM MyTable

WHERE 1=1

Lalu saya periksa dengan nomor lain

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

dll. Setelah melakukan semua pemeriksaan, kueri menjalankan kota adalah sama. bahkan tanpa klausa mana. Saya bukan penggemar sintaks

JonWay
sumber
1

Saya melakukan ini biasanya ketika saya sedang membangun SQL dinamis untuk laporan yang memiliki banyak nilai dropdown yang dapat dipilih pengguna. Karena pengguna mungkin atau mungkin tidak memilih nilai dari setiap dropdown, kami akhirnya mendapatkan kesulitan mencari tahu kondisi mana yang merupakan klausa pertama di mana. Jadi kami mengisi kueri dengan where 1=1pada akhirnya dan menambahkan semua klausa tempat setelah itu.

Sesuatu seperti

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

Kemudian kita akan membangun mana klausa seperti ini dan memberikannya sebagai nilai parameter

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

Karena pemilihan klausa tidak diketahui oleh kami saat runtime, maka hal ini membantu kami dalam menemukan apakah akan menyertakan 'AND' or 'WHERE'.

Zo Has
sumber
0

Menggunakan predicate like 1=1adalah petunjuk normal yang terkadang digunakan untuk memaksa rencana akses untuk menggunakan atau tidak menggunakan pemindaian indeks. Alasan mengapa ini digunakan adalah ketika Anda menggunakan kueri gabungan multi-bersarang dengan banyak predikat di klausa di mana kadang-kadang bahkan menggunakan semua indeks menyebabkan rencana akses untuk membaca setiap tabel - pemindaian tabel penuh. Ini hanyalah 1 dari banyak petunjuk yang digunakan oleh DBA untuk mengelabui dbms agar menggunakan jalur yang lebih efisien. Hanya saja, jangan melemparkan satu; Anda memerlukan dba untuk menganalisis kueri karena tidak selalu berfungsi.

Big Al
sumber
4
Apakah Anda memiliki kutipan yang mendokumentasikan perilaku ini untuk beberapa database?
Joe
0

Berikut ini adalah use case ... namun saya tidak terlalu peduli dengan teknis mengapa saya harus menggunakan 1 = 1. Saya menulis fungsi, menggunakan pyodbc untuk mengambil beberapa data dari SQL Server. Saya mencari cara untuk memaksa pengisi setelah wherekata kunci dalam kode saya. Ini memang saran yang bagus:

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

Alasannya adalah karena saya tidak dapat mengimplementasikan kata kunci 'where' bersama-sama di dalam variabel klausa _where. Jadi, saya pikir menggunakan kondisi dummy yang mengevaluasi true akan dilakukan sebagai pengisi.

SMS
sumber
-1

Saya pertama kali menemukan ini kembali dengan ADO dan asp klasik, jawaban yang saya dapatkan adalah: kinerja. jika Anda melakukan yang lurus

Select * from tablename

dan mengirimkannya sebagai perintah / teks sql Anda akan mendapatkan peningkatan kinerja yang nyata dengan

Where 1=1

menambahkan, itu perbedaan yang terlihat. ada hubungannya dengan header tabel yang dikembalikan segera setelah kondisi pertama terpenuhi, atau kegilaan lainnya, bagaimanapun, itu mempercepat segalanya.

jackberry
sumber
3
Jika itu benar, mengapa DBMS tidak selalu menambahkan itu?
Carcamano
5
Bisakah Anda menghasilkan bukti?
Peter G.