Lakukan while loop di SQL Server 2008

120

Apakah ada metode untuk mengimplementasikan do whileloop di SQL server 2008?

Nithesh Narayanan
sumber
5
Jawaban yang diberikan Rahul memang benar, tapi apa sebenarnya yang ingin Anda capai? Loop mahal dibandingkan dengan solusi berbasis set. Mungkin mungkin untuk menghindari loop sama sekali.
Lieven Keersmaekers
Jangan gunakan loop jika memungkinkan dan saya akan memperkirakan bahwa 95% dari waktu atau lebih adalah mungkin untuk menghindarinya. Loop dan cursor adalah pembunuh performa dan tidak boleh ditulis oleh siapa pun yang bukan DBA berpengalaman dengan setidaknya lima tahun penyetelan performa.
HLGEM
1
Er. sedikit dramatis di sana HLGEM, loop dan kursor sebenarnya cukup rapi selama Anda tidak mengulang setiap baris dalam tabel. Jika Anda memiliki daftar kategori atau situs atau sesuatu yang tingkatnya relatif tinggi, maka loop mungkin menjadi cara paling efisien untuk menjalankan kueri Anda.
Geoff Griswald

Jawaban:

190

Saya tidak yakin tentang DO-WHILE IN MS SQL Server 2008 tetapi Anda dapat mengubah logika loop WHILE Anda, sehingga dapat MENGGUNAKAN seperti DO-WHILE loop.

Contoh diambil dari sini: http://blog.sqlauthority.com/2007/10/24/sql-server-simple-example-of- While-loop-with-continue- and- break-keywords/

  1. Contoh WHILE Loop

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
    END
    GO

    ResultSet:

    1
    2
    3
    4
    5
  2. Contoh WHILE Loop dengan kata kunci BREAK

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        IF @intFlag = 4
            BREAK;
    END
    GO

    ResultSet:

    1
    2
    3
  3. Contoh WHILE Loop dengan kata kunci CONTINUE dan BREAK

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        CONTINUE;
        IF @intFlag = 4 -- This will never executed
            BREAK;
    END
    GO

    ResultSet:

    1
    2
    3
    4
    5

Tetapi cobalah untuk menghindari loop pada level database. Referensi .

Pratik
sumber
17
Contoh yang sama diberikan di sini, apakah Anda penulis situs web ini? blog.sqlauthority.com/2007/10/24/…
anar khalilov
1
Dia tidak, tapi mengapa itu penting? Jawaban yang benar diberikan. Menautkan ke situs web lain merepotkan, menyalin dan menempelkan jawabannya di sini sangat membantu.
Geoff Griswald
61

Jika Anda tidak terlalu tersinggung dengan GOTOkata kunci tersebut, ini dapat digunakan untuk mensimulasikan a DO/ WHILEdalam T-SQL. Pertimbangkan contoh yang agak tidak masuk akal berikut yang ditulis dalam pseudocode:

SET I=1
DO
 PRINT I
 SET I=I+1
WHILE I<=10

Berikut adalah kode T-SQL yang setara menggunakan goto:

DECLARE @I INT=1;
START:                -- DO
  PRINT @I;
  SET @I+=1;
IF @I<=10 GOTO START; -- WHILE @I<=10

Perhatikan pemetaan satu lawan satu antara GOTOsolusi yang diaktifkan dan yang asli DO/ WHILEpseudocode. Implementasi serupa menggunakan WHILEloop akan terlihat seperti:

DECLARE @I INT=1;
WHILE (1=1)              -- DO
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF NOT (@I<=10) BREAK; -- WHILE @I<=10
 END

Sekarang, tentu saja Anda dapat menulis ulang contoh khusus ini sebagai WHILEloop sederhana , karena ini bukan kandidat yang baik untuk sebuah DO/ WHILEkonstruksi. Penekanannya adalah pada contoh singkatnya daripada penerapan, karena kasus sah yang membutuhkan a DO/ WHILEjarang terjadi.


REPEAT / UNTIL, siapa saja (TIDAK bekerja di T-SQL)?

SET I=1
REPEAT
  PRINT I
  SET I=I+1
UNTIL I>10

... dan GOTOsolusi berbasis di T-SQL:

DECLARE @I INT=1;
START:                    -- REPEAT
  PRINT @I;
  SET @I+=1;
IF NOT(@I>10) GOTO START; -- UNTIL @I>10

Melalui penggunaan kreatif GOTOdan inversi logika melalui NOTkata kunci, ada hubungan yang sangat erat antara kodesemu asli dan GOTOsolusi berbasis. Solusi serupa menggunakan WHILEloop terlihat seperti:

DECLARE @I INT=1;
WHILE (1=1)       -- REPEAT
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF @I>10 BREAK; -- UNTIL @I>10
 END

Argumen dapat dibuat bahwa untuk kasus REPEAT/ UNTIL, WHILEsolusi berbasis lebih sederhana, karena kondisi if tidak terbalik. Di sisi lain juga lebih bertele-tele.

Jika bukan karena semua penghinaan seputar penggunaan GOTO, ini bahkan mungkin menjadi solusi idiomatik untuk beberapa saat ketika konstruksi perulangan (jahat) khusus ini diperlukan dalam kode T-SQL demi kejelasan.

Gunakan ini sesuai kebijaksanaan Anda, cobalah untuk tidak membuat marah sesama pengembang ketika mereka menangkap Anda menggunakan banyak fitnah GOTO.

Michael Goldshteyn
sumber
6
+1: pasti menjawab pertanyaan dengan lebih baik daripada jawaban yang diterima.
Louis Kottmann
Saya lebih suka pendekatan WHILE (1 = 1), karena sesuai dengan tujuan secara fungsional tanpa menggunakan GOTO yang ditakuti.
kad81
Kedua metode tersebut valid. Saya suka pseudo-loop menggunakan GOTO, ini cukup pintar.
Geoff Griswald
18

Sepertinya saya ingat pernah membaca artikel ini lebih dari sekali, dan jawabannya hanya mendekati yang saya butuhkan.

Biasanya ketika saya berpikir saya akan membutuhkan DO WHILEdi T-SQL itu karena saya mengulang kursor, dan saya mencari kejelasan optimal (vs. kecepatan optimal). Di T-SQL yang sepertinya cocok dengan WHILE TRUE/ IF BREAK.

Jika itu skenario yang membawa Anda ke sini, cuplikan ini dapat menghemat waktu Anda. Jika tidak, selamat datang kembali, saya. Sekarang saya yakin saya pernah ke sini lebih dari sekali. :)

DECLARE Id INT, @Title VARCHAR(50)
DECLARE Iterator CURSOR FORWARD_ONLY FOR
SELECT Id, Title FROM dbo.SourceTable
OPEN Iterator
WHILE 1=1 BEGIN
    FETCH NEXT FROM @InputTable INTO @Id, @Title
    IF @@FETCH_STATUS < 0 BREAK
    PRINT 'Do something with ' + @Title
END
CLOSE Iterator
DEALLOCATE Iterator

Sayangnya, T-SQL tampaknya tidak menawarkan cara yang lebih bersih untuk mendefinisikan operasi loop secara tunggal, daripada loop tak terbatas ini.

shannon
sumber
Menggunakan Cursor bukanlah pilihan yang baik karena membutuhkan lebih banyak sumber daya yang sebenarnya dibutuhkan.
greektreat
10
@greektreat: Terima kasih atas downvote-nya :), tapi saya bingung! Jika "kursor tidak pernah bukan merupakan pilihan yang baik", maka itu harus selalu menjadi pilihan yang baik, jadi mengapa downvote? Serius, bagaimanapun, jelas kursor memiliki banyak kegunaan yang cukup praktis: terhadap tabel pribadi, untuk operasi kecil di mana kejelasan / singkat> kinerja, untuk tugas pemeliharaan, di mana operasi deterministik tidak tersedia, untuk operasi tertentu harus terjadi sebagai transaksi atom, dll. Dalam kasus saya baru-baru ini, saya menelan variabel tabel masuk, pribadi ke prosedur saya yang tersimpan. Basa-basi mutlak bukanlah ide yang bagus!
shannon
5
@greektreat: singkatnya, terkadang data iterasi adalah opsi HANYA. Saya kira Anda masih bisa berargumen bahwa ini bukan pilihan yang baik dalam kasus itu, tetapi itu tidak berarti kode semacam ini tidak diperlukan dan perlu downvote.
shannon
1
Saya rasa ada sekumpulan orang gila di internet yang sangat, sangat marah tentang orang lain yang menggunakan loop dan kursor dalam SQL. Di situs web ini jika Anda bahkan menyebutkan menggunakan loop dalam SQL sekitar 30 detik kemudian kotak masuk Anda akan dibanjiri dengan orang-orang bodoh yang memberitahu Anda untuk tidak menggunakannya dalam keadaan APA PUN ...
Geoff Griswald
4

Anda juga dapat menggunakan variabel keluar jika Anda ingin kode Anda sedikit lebih mudah dibaca:

DECLARE @Flag int = 0
DECLARE @Done bit = 0

WHILE @Done = 0 BEGIN
    SET @Flag = @Flag + 1
    PRINT @Flag
    IF @Flag >= 5 SET @Done = 1
END

Ini mungkin akan lebih relevan ketika Anda memiliki loop yang lebih rumit dan mencoba melacak logikanya. Seperti loop yang dinyatakan mahal, jadi coba dan gunakan metode lain jika Anda bisa.

Sebris87
sumber
Maksud saya ... Kita hidup di zaman di mana server basis data kami memiliki antara 10 dan 20 inti CPU yang menganggur pada saat tertentu, dan di mana pengontrol penyimpanan kami memiliki bandwidth yang tersedia diukur dalam Gigabit, jadi saya tidak yakin ini konvensional " kebijaksanaan "bahwa" LOOP = BAD "masih berlaku.
Geoff Griswald
1

Only While Loop secara resmi didukung oleh SQL server. Jawabannya sudah ada untuk DO while loop. Saya merinci jawaban tentang cara-cara untuk mencapai berbagai jenis loop di SQL server.

Jika Anda tahu, Anda harus menyelesaikan iterasi loop terlebih dahulu, kemudian Anda dapat mencoba versi SQL server DO..WHILE atau REPEAT..UNTIL .

DO..WHILE Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..UNTIL Loop

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

UNTUK Loop

DECLARE @cnt INT = 0;

WHILE @cnt < 10
BEGIN
   PRINT 'Inside FOR LOOP';
   SET @cnt = @cnt + 1;
END;

PRINT 'Done FOR LOOP';

Referensi

Somnath Muluk
sumber
Ini tampak seperti salin-tempel-susun ulang dari stackoverflow.com/a/46362450/8239061 .
SecretAgentMan
@SecretAgentMan: Kedua jawaban menjawab pertanyaan yang berbeda. Data tambahan diberikan di kedua jawaban.
Somnath Muluk