มีวิธีการวนรอบตัวแปรตารางใน TSQL โดยไม่ใช้เคอร์เซอร์หรือไม่


243

สมมติว่าฉันมีตัวแปรตารางง่ายๆดังต่อไปนี้:

declare @databases table
(
    DatabaseID    int,
    Name        varchar(15),   
    Server      varchar(15)
)
-- insert a bunch rows into @databases

การประกาศและการใช้เคอร์เซอร์เป็นตัวเลือกเดียวของฉันหากฉันต้องการวนซ้ำแถวหรือไม่? มีวิธีอื่นอีกไหม?


3
แม้ว่าฉันไม่แน่ใจว่าปัญหาที่คุณเห็นด้วยวิธีการข้างต้น; ดูว่าสิ่งนี้ช่วยได้หรือไม่ .. databasejournal.com/features/mssql/article.php/3111031
Gishu

5
คุณสามารถให้เหตุผลแก่เราว่าทำไมคุณถึงต้องการย้ำข้ามแถวโซลูชันอื่น ๆ ที่ไม่ต้องการการวนซ้ำอาจมีอยู่ (และส่วนใหญ่จะเร็วกว่าในกรณีส่วนใหญ่)
Pop Catalin

เห็นด้วยกับป๊อป ... อาจไม่ต้องการเคอร์เซอร์ขึ้นอยู่กับสถานการณ์ แต่ theres ไม่มีปัญหากับการใช้เคอร์เซอร์ถ้าคุณจำเป็นต้อง
Shawn

3
คุณไม่ได้ระบุสาเหตุที่คุณต้องการหลีกเลี่ยงเคอร์เซอร์ โปรดระวังว่าเคอร์เซอร์อาจเป็นวิธีที่ง่ายที่สุดในการวนซ้ำ คุณอาจเคยได้ยินว่าเคอร์เซอร์นั้น 'ไม่ดี' แต่มันซ้ำไปซ้ำมาในตารางที่ไม่ดีเมื่อเทียบกับการดำเนินการตามชุด หากคุณไม่สามารถหลีกเลี่ยงการวนซ้ำเคอร์เซอร์อาจเป็นวิธีที่ดีที่สุด การล็อคเป็นปัญหาอีกอย่างหนึ่งสำหรับเคอร์เซอร์ แต่นั่นไม่เกี่ยวข้องเมื่อใช้ตัวแปรตาราง
JacquesB

1
การใช้เคอร์เซอร์ไม่ใช่ตัวเลือกเดียวของคุณแต่ถ้าคุณไม่มีวิธีหลีกเลี่ยงวิธีการแบบทีละแถวมันจะเป็นตัวเลือกที่ดีที่สุดของคุณ เคอร์เซอร์เป็นโครงสร้างภายในที่มีประสิทธิภาพมากกว่าและมีข้อผิดพลาดน้อยกว่าการทำลูปในขณะที่คุณโง่ เวลาส่วนใหญ่คุณเพียงแค่ต้องใช้STATICตัวเลือกเพื่อลบการตรวจสอบตารางฐานและการล็อกที่มีอยู่เป็นค่าเริ่มต้นและทำให้คนส่วนใหญ่เชื่อว่า CURSORs นั้นชั่วร้าย @JacquesB ใกล้มาก: ตรวจสอบอีกครั้งเพื่อดูว่าแถวผลลัพธ์ยังคงมีอยู่ + การล็อกเป็นปัญหาหรือไม่ และSTATICมักจะแก้ไขว่า :-)
โซโลมอน Rutzky

คำตอบ:


376

ก่อนอื่นคุณควรแน่ใจอย่างยิ่งว่าคุณจำเป็นต้องทำซ้ำในแต่ละแถวการดำเนินการที่ตั้งค่าไว้จะทำงานได้เร็วขึ้นในทุกกรณีที่ฉันสามารถนึกได้และโดยปกติจะใช้รหัสที่ง่ายกว่า

ขึ้นอยู่กับข้อมูลของคุณอาจเป็นไปได้ที่จะวนซ้ำโดยใช้SELECTข้อความสั่งที่แสดงด้านล่าง:

Declare @Id int

While (Select Count(*) From ATable Where Processed = 0) > 0
Begin
    Select Top 1 @Id = Id From ATable Where Processed = 0

    --Do some processing here

    Update ATable Set Processed = 1 Where Id = @Id 

End

อีกทางเลือกหนึ่งคือการใช้ตารางชั่วคราว:

Select *
Into   #Temp
From   ATable

Declare @Id int

While (Select Count(*) From #Temp) > 0
Begin

    Select Top 1 @Id = Id From #Temp

    --Do some processing here

    Delete #Temp Where Id = @Id

End

ตัวเลือกที่คุณควรเลือกขึ้นอยู่กับโครงสร้างและปริมาณของข้อมูลของคุณ

หมายเหตุ:หากคุณใช้ SQL Server คุณจะสามารถใช้งานได้ดีกว่าโดยใช้:

WHILE EXISTS(SELECT * FROM #Temp)

การใช้COUNTจะต้องแตะทุกแถวในตารางEXISTSเพียงต้องการสัมผัสแถวแรก (ดูคำตอบของโจเซฟด้านล่าง)


"Select Top 1 @Id = Id จาก ATable" ควรเป็น "Select Top 1 @Id = Id จาก ATable โดยที่ Processed = 0"
Amzath

10
หากใช้ SQL Server ดูคำตอบของ Josef ด้านล่างเพื่อปรับแต่งเล็กน้อยตามด้านบน
Polshgiant

3
คุณช่วยอธิบายได้ไหมว่าทำไมถึงดีกว่าการใช้เคอร์เซอร์
marco-fiset

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

@peterh คุณถูกต้อง และในความเป็นจริงคุณมักจะสามารถหลีกเลี่ยง "ข้อเสียปกติ" เหล่านั้นได้โดยใช้STATICตัวเลือกที่คัดลอกผลการตั้งค่าไปยังตารางชั่วคราวและด้วยเหตุนี้คุณจึงไม่ได้ล็อคหรือตรวจสอบตารางฐาน :-) อีกต่อไป
โซโลมอน Rutzky

132

เพียงบันทึกย่อหากคุณใช้ SQL Server (2008 และสูงกว่า) ตัวอย่างที่มี:

While (Select Count(*) From #Temp) > 0

จะได้รับการบริการที่ดีขึ้นด้วย

While EXISTS(SELECT * From #Temp)

การนับจะต้องสัมผัสทุกแถวในตารางEXISTSเพียงต้องการสัมผัสแถวแรก


9
นี่ไม่ใช่คำตอบ แต่เป็นความเห็น / การปรับปรุงในคำตอบของ Martynw
Hammad Khan

7
เนื้อหาของบันทึกย่อนี้บังคับให้ฟังก์ชันการจัดรูปแบบดีกว่าความคิดเห็นฉันขอแนะนำให้ผนวกที่คำตอบ
Custodio

2
ใน SQL เวอร์ชันที่ใหม่กว่าตัวเพิ่มประสิทธิภาพคิวรีจะฉลาดพอที่จะรู้ว่าเมื่อคุณเขียนสิ่งแรกคุณหมายถึงอันดับที่สองและปรับให้เหมาะสมเพื่อหลีกเลี่ยงการสแกนตาราง
Dan Def

39

นี่คือวิธีที่ฉันทำ:

declare @RowNum int, @CustId nchar(5), @Name1 nchar(25)

select @CustId=MAX(USERID) FROM UserIDs     --start with the highest ID
Select @RowNum = Count(*) From UserIDs      --get total number of records
WHILE @RowNum > 0                          --loop until no more records
BEGIN   
    select @Name1 = username1 from UserIDs where USERID= @CustID    --get other info from that row
    print cast(@RowNum as char(12)) + ' ' + @CustId + ' ' + @Name1  --do whatever

    select top 1 @CustId=USERID from UserIDs where USERID < @CustID order by USERID desc--get the next one
    set @RowNum = @RowNum - 1                               --decrease count
END

ไม่มีเคอร์เซอร์ไม่มีตารางชั่วคราวไม่มีคอลัมน์เพิ่มเติม คอลัมน์ USERID ต้องเป็นจำนวนเต็มที่ไม่ซ้ำกันเนื่องจากคีย์หลักส่วนใหญ่คือ


26

กำหนดตารางอุณหภูมิของคุณเช่นนี้ -

declare @databases table
(
    RowID int not null identity(1,1) primary key,
    DatabaseID    int,
    Name        varchar(15),   
    Server      varchar(15)
)

-- insert a bunch rows into @databases

จากนั้นทำเช่นนี้ -

declare @i int
select @i = min(RowID) from @databases
declare @max int
select @max = max(RowID) from @databases

while @i <= @max begin
    select DatabaseID, Name, Server from @database where RowID = @i --do some stuff
    set @i = @i + 1
end

16

นี่คือวิธีที่ฉันจะทำ:

Select Identity(int, 1,1) AS PK, DatabaseID
Into   #T
From   @databases

Declare @maxPK int;Select @maxPK = MAX(PK) From #T
Declare @pk int;Set @pk = 1

While @pk <= @maxPK
Begin

    -- Get one record
    Select DatabaseID, Name, Server
    From @databases
    Where DatabaseID = (Select DatabaseID From #T Where PK = @pk)

    --Do some processing here
    -- 

    Select @pk = @pk + 1
End

[แก้ไข] เพราะฉันอาจข้ามคำว่า "ตัวแปร" เมื่อฉันอ่านคำถามเป็นครั้งแรกนี่คือการตอบกลับที่อัปเดต ...


declare @databases table
(
    PK            int IDENTITY(1,1), 
    DatabaseID    int,
    Name        varchar(15),   
    Server      varchar(15)
)
-- insert a bunch rows into @databases
--/*
INSERT INTO @databases (DatabaseID, Name, Server) SELECT 1,'MainDB', 'MyServer'
INSERT INTO @databases (DatabaseID, Name, Server) SELECT 1,'MyDB',   'MyServer2'
--*/

Declare @maxPK int;Select @maxPK = MAX(PK) From @databases
Declare @pk int;Set @pk = 1

While @pk <= @maxPK
Begin

    /* Get one record (you can read the values into some variables) */
    Select DatabaseID, Name, Server
    From @databases
    Where PK = @pk

    /* Do some processing here */
    /* ... */ 

    Select @pk = @pk + 1
End

4
ดังนั้นโดยทั่วไปคุณกำลังทำเคอร์เซอร์ แต่ไม่มีประโยชน์ทั้งหมดของเคอร์เซอร์
Shawn

1
... โดยไม่ต้องล็อคตารางที่ถูกนำมาใช้ในขณะที่การประมวลผล ... เช่นนี้เป็นหนึ่งในผลประโยชน์ของเคอร์เซอร์ :)
leoinfo

3
ตาราง? มันเป็นตารางที่มีความหลากหลาย - ไม่สามารถเข้าถึงพร้อมกันได้
DenNukem

DenNukem คุณพูดถูกฉันคิดว่าฉัน "ข้าม" คำว่า "ตัวแปร" เมื่อฉันอ่านคำถามในเวลานั้น ... ฉันจะเพิ่มบันทึกย่อลงในการตอบกลับครั้งแรกของฉัน
le ชรา

ฉันต้องเห็นด้วยกับ DenNukem และ Shawn เพราะเหตุใดทำไมคุณถึงมีความยาวเพื่อหลีกเลี่ยงการใช้เคอร์เซอร์ อีกครั้ง: เขาต้องการวนซ้ำตัวแปรตารางไม่ใช่ตารางดั้งเดิม !!!
เตอร์

10

หากคุณไม่มีทางเลือกนอกจากไปทีละแถวการสร้างเคอร์เซอร์ FAST_FORWARD มันจะเร็วเท่ากับการสร้างวงในขณะที่และง่ายต่อการรักษาในระยะยาว

FAST_FORWARD ระบุเคอร์เซอร์ FORWARD_ONLY, READ_ONLY พร้อมการเปิดใช้งานการเพิ่มประสิทธิภาพ FAST_FORWARD ไม่สามารถระบุได้หากระบุ SCROLL หรือ FOR_UPDATE


2
ใช่ ขณะที่ผมแสดงความคิดเห็นอื่น ๆ ผมยังไม่เห็นข้อโต้แย้งใด ๆ ว่าทำไมไม่ใช้เคอร์เซอร์เมื่อคดีคือการย้ำกว่าตัวแปรตาราง FAST_FORWARDเคอร์เซอร์เป็นวิธีการแก้ดี (upvote)
peterh

5

วิธีอื่นโดยไม่ต้องเปลี่ยนสคีมาของคุณหรือใช้ตารางชั่วคราว:

DECLARE @rowCount int = 0
  ,@currentRow int = 1
  ,@databaseID int
  ,@name varchar(15)
  ,@server varchar(15);

SELECT @rowCount = COUNT(*)
FROM @databases;

WHILE (@currentRow <= @rowCount)
BEGIN
  SELECT TOP 1
     @databaseID = rt.[DatabaseID]
    ,@name = rt.[Name]
    ,@server = rt.[Server]
  FROM (
    SELECT ROW_NUMBER() OVER (
        ORDER BY t.[DatabaseID], t.[Name], t.[Server]
       ) AS [RowNumber]
      ,t.[DatabaseID]
      ,t.[Name]
      ,t.[Server]
    FROM @databases t
  ) rt
  WHERE rt.[RowNumber] = @currentRow;

  EXEC [your_stored_procedure] @databaseID, @name, @server;

  SET @currentRow = @currentRow + 1;
END

4

คุณสามารถใช้ while loop ได้:

While (Select Count(*) From #TempTable) > 0
Begin
    Insert Into @Databases...

    Delete From #TempTable Where x = x
End

4

สิ่งนี้จะทำงานในเวอร์ชัน SQL SERVER 2012

declare @Rowcount int 
select @Rowcount=count(*) from AddressTable;

while( @Rowcount>0)
  begin 
 select @Rowcount=@Rowcount-1;
 SELECT * FROM AddressTable order by AddressId desc OFFSET @Rowcount ROWS FETCH NEXT 1 ROWS ONLY;
end 

4

น้ำหนักเบาโดยไม่ต้องสร้างตารางเพิ่มเติมหากคุณมีจำนวนเต็มIDบนตาราง

Declare @id int = 0, @anything nvarchar(max)
WHILE(1=1) BEGIN
  Select Top 1 @anything=[Anything],@id=@id+1 FROM Table WHERE ID>@id
  if(@@ROWCOUNT=0) break;

  --Process @anything

END

3
-- [PO_RollBackOnReject]  'FININV10532'
alter procedure PO_RollBackOnReject
@CaseID nvarchar(100)

AS
Begin
SELECT  *
INTO    #tmpTable
FROM   PO_InvoiceItems where CaseID = @CaseID

Declare @Id int
Declare @PO_No int
Declare @Current_Balance Money


While (Select ROW_NUMBER() OVER(ORDER BY PO_LineNo DESC) From #tmpTable) > 0
Begin
        Select Top 1 @Id = PO_LineNo, @Current_Balance = Current_Balance,
        @PO_No = PO_No
        From #Temp
        update PO_Details
        Set  Current_Balance = Current_Balance + @Current_Balance,
            Previous_App_Amount= Previous_App_Amount + @Current_Balance,
            Is_Processed = 0
        Where PO_LineNumber = @Id
        AND PO_No = @PO_No
        update PO_InvoiceItems
        Set IsVisible = 0,
        Is_Processed= 0
        ,Is_InProgress = 0 , 
        Is_Active = 0
        Where PO_LineNo = @Id
        AND PO_No = @PO_No
End
End

2

cursorผมไม่เห็นจุดที่ว่าทำไมคุณจะต้องหันไปใช้หวั่น แต่นี่คือตัวเลือกอื่นหากคุณใช้ SQL Server รุ่น 2005/2008
ใช้การเรียกซ้ำ

declare @databases table
(
    DatabaseID    int,
    Name        varchar(15),   
    Server      varchar(15)
)

--; Insert records into @databases...

--; Recurse through @databases
;with DBs as (
    select * from @databases where DatabaseID = 1
    union all
    select A.* from @databases A 
        inner join DBs B on A.DatabaseID = B.DatabaseID + 1
)
select * from DBs

2

ฉันจะให้โซลูชันตามการตั้งค่า

insert  @databases (DatabaseID, Name, Server)
select DatabaseID, Name, Server 
From ... (Use whatever query you would have used in the loop or cursor)

นี่เร็วกว่าเทคโนโลยีวนลูปใด ๆ และเขียนและบำรุงรักษาได้ง่ายกว่า


2

ฉันชอบใช้ Offset Fetch หากคุณมี ID ที่ไม่ซ้ำใครคุณสามารถจัดเรียงตารางตาม:

DECLARE @TableVariable (ID int, Name varchar(50));
DECLARE @RecordCount int;
SELECT @RecordCount = COUNT(*) FROM @TableVariable;

WHILE @RecordCount > 0
BEGIN
SELECT ID, Name FROM @TableVariable ORDER BY ID OFFSET @RecordCount - 1 FETCH NEXT 1 ROW;
SET @RecordCount = @RecordCount - 1;
END

ด้วยวิธีนี้ฉันไม่จำเป็นต้องเพิ่มเขตข้อมูลลงในตารางหรือใช้ฟังก์ชันหน้าต่าง


2

เป็นไปได้ที่จะใช้เคอร์เซอร์เพื่อทำสิ่งนี้:

สร้างฟังก์ชั่น [dbo] .f_teste_loop ส่งกลับตาราง @tabela (cod int, nome varchar (10)) เป็นการเริ่มต้น

insert into @tabela values (1, 'verde');
insert into @tabela values (2, 'amarelo');
insert into @tabela values (3, 'azul');
insert into @tabela values (4, 'branco');

return;

ปลาย

สร้างโพรซีเดอร์ [dbo] [sp_teste_loop] เมื่อเริ่มต้น

DECLARE @cod int, @nome varchar(10);

DECLARE curLoop CURSOR STATIC LOCAL 
FOR
SELECT  
    cod
   ,nome
FROM 
    dbo.f_teste_loop();

OPEN curLoop;

FETCH NEXT FROM curLoop
           INTO @cod, @nome;

WHILE (@@FETCH_STATUS = 0)
BEGIN
    PRINT @nome;

    FETCH NEXT FROM curLoop
           INTO @cod, @nome;
END

CLOSE curLoop;
DEALLOCATE curLoop;

ปลาย


1
ไม่ใช่คำถามเดิม "ไม่ใช้เคอร์เซอร์" ใช่หรือไม่
เฟอร์นันโดกอนซาเลซซานเชซ

1

ฉันเห็นด้วยกับโพสต์ก่อนหน้าว่าการดำเนินการแบบ set-based จะทำงานได้ดีขึ้น แต่ถ้าคุณจำเป็นต้องทำซ้ำในแถวต่อไปนี้เป็นวิธีที่ฉันจะทำ:

  1. เพิ่มเขตข้อมูลใหม่ให้กับตัวแปรตารางของคุณ (บิตชนิดข้อมูลค่าเริ่มต้น 0)
  2. ใส่ข้อมูลของคุณ
  3. เลือกแถวบนสุด 1 ตำแหน่งที่ fUsed = 0 (หมายเหตุ: fUsed คือชื่อของเขตข้อมูลในขั้นตอนที่ 1)
  4. ทำการประมวลผลสิ่งที่คุณต้องทำ
  5. อัปเดตระเบียนในตัวแปรตารางของคุณโดยการตั้งค่า fUsed = 1 สำหรับบันทึก
  6. เลือกระเบียนที่ไม่ได้ใช้ถัดไปจากตารางและทำซ้ำกระบวนการ

    DECLARE @databases TABLE  
    (  
        DatabaseID  int,  
        Name        varchar(15),     
        Server      varchar(15),   
        fUsed       BIT DEFAULT 0  
    ) 
    
    -- insert a bunch rows into @databases
    
    DECLARE @DBID INT
    
    SELECT TOP 1 @DBID = DatabaseID from @databases where fUsed = 0 
    
    WHILE @@ROWCOUNT <> 0 and @DBID IS NOT NULL  
    BEGIN  
        -- Perform your processing here  
    
        --Update the record to "used" 
    
        UPDATE @databases SET fUsed = 1 WHERE DatabaseID = @DBID  
    
        --Get the next record  
        SELECT TOP 1 @DBID = DatabaseID from @databases where fUsed = 0   
    END

1

ขั้นที่ 1: คำสั่ง select ด้านล่างสร้างตารางชั่วคราวพร้อมหมายเลขแถวที่ไม่ซ้ำกันสำหรับแต่ละระเบียน

select eno,ename,eaddress,mobno int,row_number() over(order by eno desc) as rno into #tmp_sri from emp 

ขั้นที่ 2: ประกาศตัวแปรที่จำเป็น

DECLARE @ROWNUMBER INT
DECLARE @ename varchar(100)

ขั้นตอนที่ 3: นับจำนวนแถวทั้งหมดจากตารางชั่วคราว

SELECT @ROWNUMBER = COUNT(*) FROM #tmp_sri
declare @rno int

Step4: วนตาราง temp ตามหมายเลขแถวที่ไม่ซ้ำกันสร้างใน temp

while @rownumber>0
begin
  set @rno=@rownumber
  select @ename=ename from #tmp_sri where rno=@rno  **// You can take columns data from here as many as you want**
  set @rownumber=@rownumber-1
  print @ename **// instead of printing, you can write insert, update, delete statements**
end

1

วิธีการนี้ต้องการเพียงหนึ่งตัวแปรและไม่ลบแถวใด ๆ ออกจากฐานข้อมูล @ ฉันรู้ว่ามีคำตอบมากมายที่นี่ แต่ฉันไม่เห็นคำตอบที่ใช้ MIN เพื่อรับ ID ถัดไปของคุณเช่นนี้

DECLARE @databases TABLE
(
    DatabaseID    int,
    Name        varchar(15),   
    Server      varchar(15)
)

-- insert a bunch rows into @databases

DECLARE @CurrID INT

SELECT @CurrID = MIN(DatabaseID)
FROM @databases

WHILE @CurrID IS NOT NULL
BEGIN

    -- Do stuff for @CurrID

    SELECT @CurrID = MIN(DatabaseID)
    FROM @databases
    WHERE DatabaseID > @CurrID

END

1

นี่คือทางออกของฉันซึ่งใช้ลูปไม่สิ้นสุดBREAKคำสั่งและ@@ROWCOUNTฟังก์ชัน ไม่จำเป็นต้องใช้เคอร์เซอร์หรือตารางชั่วคราวและฉันต้องเขียนเพียงหนึ่งแบบสอบถามเพื่อให้ได้แถวถัดไปใน@databasesตาราง:

declare @databases table
(
    DatabaseID    int,
    [Name]        varchar(15),   
    [Server]      varchar(15)
);


-- Populate the [@databases] table with test data.
insert into @databases (DatabaseID, [Name], [Server])
select X.DatabaseID, X.[Name], X.[Server]
from (values 
    (1, 'Roger', 'ServerA'),
    (5, 'Suzy', 'ServerB'),
    (8675309, 'Jenny', 'TommyTutone')
) X (DatabaseID, [Name], [Server])


-- Create an infinite loop & ensure that a break condition is reached in the loop code.
declare @databaseId int;

while (1=1)
begin
    -- Get the next database ID.
    select top(1) @databaseId = DatabaseId 
    from @databases 
    where DatabaseId > isnull(@databaseId, 0);

    -- If no rows were found by the preceding SQL query, you're done; exit the WHILE loop.
    if (@@ROWCOUNT = 0) break;

    -- Otherwise, do whatever you need to do with the current [@databases] table row here.
    print 'Processing @databaseId #' + cast(@databaseId as varchar(50));
end

ฉันเพิ่งรู้ว่า@ControlFreakแนะนำวิธีนี้ก่อนฉัน ฉันเพียงแค่เพิ่มความคิดเห็นและตัวอย่างที่ชัดเจนยิ่งขึ้น
Mass Dot Net

0

นี่คือรหัสที่ฉันใช้ 2008 R2 รหัสนี้ที่ฉันใช้คือการสร้างดัชนีในฟิลด์สำคัญ (SSNO & EMPR_NO) n นิทานทั้งหมด

if object_ID('tempdb..#a')is not NULL drop table #a

select 'IF EXISTS (SELECT name FROM sysindexes WHERE name ='+CHAR(39)+''+'IDX_'+COLUMN_NAME+'_'+SUBSTRING(table_name,5,len(table_name)-3)+char(39)+')' 
+' begin DROP INDEX [IDX_'+COLUMN_NAME+'_'+SUBSTRING(table_name,5,len(table_name)-3)+'] ON '+table_schema+'.'+table_name+' END Create index IDX_'+COLUMN_NAME+'_'+SUBSTRING(table_name,5,len(table_name)-3)+ ' on '+ table_schema+'.'+table_name+' ('+COLUMN_NAME+') '   'Field'
,ROW_NUMBER() over (order by table_NAMe) as  'ROWNMBR'
into #a
from INFORMATION_SCHEMA.COLUMNS
where (COLUMN_NAME like '%_SSNO_%' or COLUMN_NAME like'%_EMPR_NO_')
    and TABLE_SCHEMA='dbo'

declare @loopcntr int
declare @ROW int
declare @String nvarchar(1000)
set @loopcntr=(select count(*)  from #a)
set @ROW=1  

while (@ROW <= @loopcntr)
    begin
        select top 1 @String=a.Field 
        from #A a
        where a.ROWNMBR = @ROW
        execute sp_executesql @String
        set @ROW = @ROW + 1
    end 

0
SELECT @pk = @pk + 1

จะดีกว่า:

SET @pk += @pk

หลีกเลี่ยงการใช้ SELECT หากคุณไม่ได้อ้างอิงตารางเป็นเพียงการกำหนดค่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.