ไวยากรณ์ของ for-loop ใน SQL Server


238

ไวยากรณ์ของforลูปใน TSQL คืออะไร


10
SQL เป็นภาษาที่แตกต่างกันมากเมื่อเทียบกับสิ่งที่คุณคุ้นเคย มันมุ่งเน้นไปที่สิ่งที่ไม่ว่า คุณบอก SQL Server ว่าคุณต้องการผลลัพธ์อะไรและปล่อยให้มันคิดวิธีสร้างคำตอบ หรือเพื่อพูดใหม่ในสิ่งที่ฉันเพิ่งพูดไป - ไม่มีการวนซ้ำใน SQL
Damien_The_Unbeliever

5
WHILE @I < 10; SET @I = @I + 1; BEGIN; ...; END? อย่างไรก็ตามสิ่งนี้ไม่ควรใช้สำหรับการประมวลผลแบบสอบถามส่วนใหญ่ (แต่บางครั้งก็จำเป็นสำหรับการจัดการที่จำเป็น) มีคำแนะนำ / คำแนะนำดังกล่าวมากมายบน Google โดยใช้การค้นหา "tsql for loop"

7
หลีกเลี่ยงการวนซ้ำเพื่อเข้าร่วมและตั้งค่าการดำเนินการ
Oded

2
หากคุณไม่ใช่ผู้เชี่ยวชาญใน SQL คุณไม่ควรพิจารณาใช้ลูป มีเพียงไม่กี่เงื่อนไขที่จำเป็นต้องใช้และใช้เวลาที่เหลืออยู่ส่วนใหญ่การใช้การวนซ้ำนั้นเทียบเท่ากับการผลักรถของคุณแทนที่จะขับรถ เรียนรู้ที่จะคิดในแง่ของชุดข้อมูลแทนการวนซ้ำผ่านระเบียน การวนซ้ำเป็นฟังก์ชันระดับผู้เชี่ยวชาญไม่ใช่เพราะไวยากรณ์ยาก แต่เนื่องจากคุณต้องทราบว่าคุณสามารถทำอันตรายกับมันได้มากแค่ไหนก่อนที่คุณจะได้รับอนุญาตให้ใช้
HLGEM

2
บางครั้งมันอาจถูกใช้เพื่อสร้างข้อมูลทดสอบอย่างรวดเร็วในฐานข้อมูลการทดสอบที่คุณเพิ่งจะลบในไม่ช้าหลังจากนั้น ในกรณีดังกล่าวการใช้สิ่งนี้ทำให้ไม่จำเป็นต้องผ่านโปรแกรมแยกต่างหากที่เขียนด้วยภาษา C # และวิศวกรรมไม่ใช่เรื่องที่สำคัญเป็นพิเศษ อีกครั้งฉันแค่พูดแบบนี้ในแง่ของข้อมูลการทดสอบ
Panzercrisis

คำตอบ:


210

T-SQL ไม่มีFORลูป แต่มีWHILEลูป
ในขณะที่ (Transact-SQL)

WHILE Boolean_expression
BEGIN

END

8
เข้าร่วม (และการดำเนินการตั้งค่า) ควรเป็นที่นิยมมากกว่าการสร้างวนลูปใน SQL
Oded

6
(โดยเฉพาะอย่างยิ่งสำหรับผู้ที่ยังใหม่กับ SQL) สิ่งที่ Damien กล่าวว่า: "SQL เป็นภาษาที่แตกต่างกันมากเมื่อเทียบกับสิ่งที่คุณคุ้นเคย" มันเน้นเรื่องอะไรไม่ใช่วิธีคุณบอก SQL Server ว่าอะไร ผลลัพธ์ที่คุณต้องการและปล่อยให้มันหาวิธีสร้างคำตอบ "
ypercubeᵀᴹ

1
มันน่าสนใจที่จะทราบว่าเอกสารของ MS ผิดที่นี่จริงๆ ในขณะที่ไม่ได้ใช้นิพจน์บูลีน - มันใช้คำกริยา - ซึ่งนอกจากจะสามารถประเมินเป็น TRUE หรือ FALSE ก็อาจเป็น UNKNOWN
Damien_The_Unbeliever

360

ไม่มีการ for-loop เพียง while-loop:

DECLARE @i int = 0

WHILE @i < 20
BEGIN
    SET @i = @i + 1
    /* do some work */
END

20
ไม่ว่าจะเป็นถ้าคุณตั้งใจจะใช้ดัชนีในลูปคุณอาจต้องการเพิ่มสิ่งสุดท้ายแทนอันดับแรกขึ้นอยู่กับกรณีการใช้งานของคุณ
jinglesthula

3
นอกจากนี้โปรดทราบว่าไม่สนับสนุนค่าเริ่มต้นสำหรับตัวแปรท้องถิ่นใน SQL ธรรมดา ดังนั้นคุณต้องแยกSET @i = 0ก่อนสำหรับการวนซ้ำ
Nux

1
@Nux: 0 ถูกตั้งค่าในระหว่างการประกาศอย่างชัดเจน
TcKs

7
ใช่ แต่ใช้ไม่ได้กับเซิร์ฟเวอร์ SQL รุ่นเก่า (อย่างน้อยไม่ใช่ในปี 2005)
Nux

นอกจากนี้ควรสังเกตว่าโดยทั่วไปแล้วงานจะเสร็จสิ้นก่อนที่จำนวนเต็มจะเพิ่มขึ้น สำหรับลูปจำนวนมากใน SQL ใช้จำนวนเต็มนั้นจริง ๆ ในการทำงาน (วนซ้ำจากแถวหนึ่งไปอีกแถวหรือผลลัพธ์ในตาราง temp) และอาจถูกโยนออกหากการเพิ่มเกิดขึ้นที่จุดเริ่มต้นของวัฏจักรแทนที่จะจบ
CSS

34

ข้อมูลเสริม

เพียงแค่เพิ่มเป็นไม่มีใครได้โพสต์คำตอบที่มีวิธีการที่จริงย้ำแม้ว่าจะเป็นชุดข้อมูลภายในห่วงคุณสามารถใช้คำหลักที่ชดเชยเรียก

การใช้

DECLARE @i INT = 0;
SELECT @count=  Count(*) FROM {TABLE}

WHILE @i <= @count
BEGIN

    SELECT * FROM {TABLE}
    ORDER BY {COLUMN}
    OFFSET @i ROWS   
    FETCH NEXT 1 ROWS ONLY  

    SET @i = @i + 1;

END

2
ทางเลือกที่ดีในการใช้เคอร์เซอร์
DanteTheSmith

28

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

13
ยินดีต้อนรับสู่ Stack Overflow! คุณจะพิจารณาเพิ่มคำบรรยายเพื่ออธิบายว่าทำไมรหัสนี้จึงใช้งานได้และอะไรทำให้เป็นคำตอบของคำถาม สิ่งนี้จะเป็นประโยชน์กับผู้ที่ถามคำถามและใครก็ตามที่เข้ามา
Andrew Barber

18
นี่คือการอธิบายตนเอง
Edward Olamisan

4
สิ่งนี้ไม่อธิบายตนเองได้อย่างไร ฉันมีคำถามเดียวกันฉันเข้าใจคำตอบทันที
DanteTheSmith

1
คำตอบนี้แตกต่างจาก @TcKs เพียงใดนอกจากการตั้งชื่อแผนการประชุม
Sushil Jadhav

7

เกี่ยวกับสิ่งนี้:

BEGIN
   Do Something
END
GO 10

... แน่นอนว่าคุณสามารถใส่เคาน์เตอร์แบบเพิ่มหน่วยไว้ข้างในได้หากคุณต้องการนับ


3
'GO 10'? SQL Server 2008 ไม่ชอบ
ทรัพยากร

7

สำหรับการวนซ้ำยังไม่ได้รับการสนับสนุนอย่างเป็นทางการโดยเซิร์ฟเวอร์ SQL มีคำตอบสำหรับการบรรลุถึงถึงวิธีการต่าง ๆ ของ Loop ฉันให้รายละเอียดคำตอบเกี่ยวกับวิธีการใช้ลูปประเภทต่างๆในเซิร์ฟเวอร์ SQL

สำหรับวง

DECLARE @cnt INT = 0;

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

PRINT 'Done FOR LOOP';

ถ้าคุณรู้คุณจะต้องวนซ้ำครั้งแรกต่อไปจากนั้นคุณสามารถลองDO .. ขณะที่หรือREPEAT..UNTILเวอร์ชันของเซิร์ฟเวอร์ SQL

DO .. ขณะที่ Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..UNTIL วนซ้ำ

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

การอ้างอิง


สิ่งนี้ดูเหมือนจะถูกคัดลอก - วาง - จัดลำดับใหม่ที่นี่: stackoverflow.com/a/46363319/8239061
SecretAgentMan

@SecretAgentMan: คำตอบทั้งคู่ตอบคำถามต่าง ๆ ข้อมูลเพิ่มเติมให้ทั้งคำตอบ
Somnath Muluk

6

NO !!คำตอบง่ายๆคือ

ไม่มีFORใน SQL แต่คุณสามารถใช้WHILEหรือGOTOเพื่อให้บรรลุตามวิธีการFORทำงานของมัน

ในขณะที่:

DECLARE @a INT = 10

WHILE @a <= 20
BEGIN
    PRINT @a
    SET @a = @a + 1
END

ไปที่ :

DECLARE @a INT = 10
a:
PRINT @a
SET @a = @a + 1
IF @a < = 20
BEGIN
    GOTO a
END

ฉันชอบคำแถลงWHILEมากกว่าGOTOเสมอ


1
ฉันชอบวิธีที่คุณพูดถึงทั้งสองทางเลือกแทน 1 เหมือนคำตอบส่วนใหญ่
DanteTheSmith

0

ในขณะที่ตัวอย่าง Loop ใน T-SQL ซึ่งแสดงรายการวันที่เริ่มต้นถึงวันที่สิ้นสุดของเดือนปัจจุบัน

DECLARE @Today DATE= GETDATE() ,
@StartOfMonth DATE ,
@EndOfMonth DATE;

DECLARE @DateList TABLE ( DateLabel VARCHAR(10) );
SET @EndOfMonth = EOMONTH(GETDATE());
SET @StartOfMonth = DATEFROMPARTS(YEAR(@Today), MONTH(@Today), 1);

WHILE @StartOfMonth <= @EndOfMonth
BEGIN
    INSERT  INTO @DateList
    VALUES  ( @StartOfMonth );
    SET @StartOfMonth = DATEADD(DAY, 1, @StartOfMonth);
END;

SELECT  DateLabel
FROM    @DateList;  

0

ลองเรียนรู้:

DECLARE @r INT = 5
DECLARE @i INT = 0
DECLARE @F varchar(max) = ''
WHILE @i < @r
BEGIN

    DECLARE @j INT = 0
    DECLARE @o varchar(max) = ''
    WHILE @j < @r - @i - 1
    BEGIN
        SET @o = @o + ' '
        SET @j += 1
    END

    DECLARE @k INT = 0
    WHILE @k < @i + 1
    BEGIN
        SET @o = @o + ' *'  -- '*'
        SET @k += 1
    END
    SET @i += 1
    SET @F = @F + @o + CHAR(13)
END
PRINT @F

ด้วยวันที่:

DECLARE @d DATE = '2019-11-01'
WHILE @d < GETDATE()
BEGIN
    PRINT @d
    SET @d = DATEADD(DAY,1,@d)
END
PRINT 'n'
PRINT @d
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.