টিএসকিউএলে কোনও কার্সার ব্যবহার না করে কোনও টেবিল ভেরিয়েবলের মধ্য দিয়ে লুপ করার কোনও উপায় আছে কি?


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
আপনি কেন সারিগুলিতে পুনরাবৃত্তি করতে চান তার কারণটি সরবরাহ করতে পারেন, পুনরাবৃত্তির প্রয়োজন হয় না এমন অন্যান্য সমাধান উপস্থিত থাকতে পারে (এবং যা বেশিরভাগ ক্ষেত্রে বড় ব্যবধানে দ্রুত হয়)
পপ ক্যাটালিন

পপ সহ একমত ... পরিস্থিতির উপর নির্ভর করে কার্সারের প্রয়োজন হতে পারে না। তবে আপনার যদি প্রয়োজন হয় তবে কার্সার ব্যবহারে কোনও সমস্যা নেই
শন

3
আপনি কেন কার্সার এড়াতে চান তা উল্লেখ করেন না। সচেতন হন যে কার্সারটি পুনরাবৃত্তি করার সহজতম উপায় হতে পারে। আপনি শুনে থাকতে পারেন যে কার্সারগুলি 'খারাপ', তবে সেট-ভিত্তিক ক্রিয়াকলাপগুলির তুলনায় এটি টেবিলগুলির চেয়ে সত্যই পুনরাবৃত্তি। যদি আপনি পুনরাবৃত্তি এড়াতে না পারেন তবে একটি কার্সার সেরা উপায় হতে পারে। লক করা কার্সারগুলির সাথে অন্য একটি সমস্যা, তবে টেবিল ভেরিয়েবল ব্যবহার করার সময় এটি প্রাসঙ্গিক নয়।
জ্যাকবিবি

1
কার্সার ব্যবহার করা আপনার একমাত্র বিকল্প নয়, তবে যদি আপনার সারি-সারি সারি পন্থা এড়ানোর কোনও উপায় না থাকে তবে এটি আপনার সেরা বিকল্প হবে। CURSORs একটি বিল্ট-ইন কনস্ট্রাক্ট যা আপনার নিজের নির্বোধ WHIP লুপটি করার চেয়ে আরও দক্ষ এবং কম ত্রুটি-প্রবণ। বেশিরভাগ সময় আপনাকে কেবল STATICবেস টেবিলগুলির নিয়মিত পুনরায় পরীক্ষা-নিরীক্ষার অপসারণ এবং ডিফল্টরূপে সেখানে থাকা লকিং অপসারণ করতে এবং বেশিরভাগ লোককে ভুলভাবে বিশ্বাস করে যে সেন্সরগুলি মন্দ। @ জ্যাক্কসবি খুব কাছাকাছি: ফলাফলের সারিটি এখনও বিদ্যমান কিনা তা পরীক্ষা করে দেখার জন্য + লক করা বিষয়গুলি। এবং STATICসাধারণত এটি স্থির করে :-)।
সলোমন রুটজকি

উত্তর:


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

আপনার পছন্দ করা উচিত বিকল্পটি আপনার ডেটার গঠন এবং ভলিউমের উপর নির্ভর করে।

দ্রষ্টব্য: আপনি যদি এসকিউএল সার্ভার ব্যবহার করেন তবে আপনাকে আরও ভালভাবে ব্যবহার করা হবে:

WHILE EXISTS(SELECT * FROM #Temp)

ব্যবহারে COUNTটেবিলের প্রতিটি একক সারি স্পর্শ করতে হবে, EXISTSকেবল প্রথমটি স্পর্শ করতে হবে ( নীচে জোসেফের উত্তর দেখুন)।


"শীর্ষস্থানীয় 1 @ আইডি = আইডিটি এটিএবল থেকে নির্বাচন করুন" হওয়া উচিত "নির্বাচনযোগ্য শীর্ষ @ @ আইডি = আইডি থেকে প্রবণতাযুক্ত যেখানে 0 ="
আমজাথ

10
যদি এসকিউএল সার্ভার ব্যবহার করে থাকেন তবে উপরের দিকে একটি ছোট ঝাঁকির জন্য নীচে জোসেফের উত্তর দেখুন।
পলশগিয়ান্ট

3
কার্সার ব্যবহারের চেয়ে কেন এটি ভাল তা আপনি ব্যাখ্যা করতে পারেন?
মার্কো ফিসেট

5
এটিকে একটি ডাউনভোট দিয়েছে। কেন সে কার্সার ব্যবহার এড়ানো উচিত? তিনি table তিহ্যবাহী টেবিল নয়, টেবিলের পরিবর্তনশীল ওভারে আউটরেটিংয়ের কথা বলছেন । আমি বিশ্বাস করি না যে এখানে কার্সারগুলির সাধারণ উত্থানগুলি প্রযোজ্য। যদি সারি-সারি সারি প্রক্রিয়াকরণটি সত্যই প্রয়োজন হয় (এবং আপনি উল্লেখ করেছেন যে তিনি প্রথমে এটি সম্পর্কে নিশ্চিত হওয়া উচিত) তবে আপনি এখানে বর্ণিত কার্সারের চেয়ে কার্সার ব্যবহার করা একটি আরও ভাল সমাধান।
পিটার

@ পেটার আপনি সঠিক আছেন এবং প্রকৃতপক্ষে, আপনি সাধারণত সেই STATICবিকল্পগুলি ব্যবহার করে যা " টেম্প টেবিলের জন্য ফলাফলটি অনুলিপি করে তা ব্যবহার করে" স্বাভাবিক ডাউনসাইডস "এড়াতে পারবেন এবং অতএব আপনি আর বেস টেবিলগুলি লক বা পুনরায় চেক করতে পারবেন না :-)।
সলোমন রুটজকি

132

কেবলমাত্র একটি দ্রুত নোট, আপনি যদি এসকিউএল সার্ভার ব্যবহার করেন (২০০৮ এবং তারপরে), উদাহরণগুলি:

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

ভাল সঙ্গে পরিবেশন করা হবে

While EXISTS(SELECT * From #Temp)

গণনাটিকে টেবিলের প্রতিটি একক সারিতে স্পর্শ করতে হবে, EXISTSকেবল প্রথমটি স্পর্শ করতে হবে।


9
এটি কোনও উত্তর নয় তবে মার্টিনউ উত্তরের মন্তব্য / বর্ধন।
হামাদ খান

7
এই নোটের সামগ্রীটি একটি মন্তব্যের চেয়ে আরও ভাল ফর্ম্যাটিং কার্যকারিতা জোর করে, আমি উত্তরে যুক্ত করার পরামর্শ দেব।
কাস্টোডিও

2
এসকিউএল-র পরবর্তী সংস্করণগুলিতে ক্যোয়ারী অপ্টিমাইজারটি যথেষ্ট চালাক যে আপনি যখন প্রথম জিনিসটি লিখবেন তখন আপনি আসলে দ্বিতীয়টি বোঝান এবং টেবিল স্ক্যানটি এড়ানোর জন্য এটিকে এটি অপ্টিমাইজ করে।
ড্যান ডেফ

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 কলামটি অবশ্যই একটি অনন্য পূর্ণসংখ্যা হতে হবে, বেশিরভাগ প্রাথমিক কীগুলি ger


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
সুতরাং আপনি মূলত একটি কার্সার করছেন, তবে একটি কার্সারের সমস্ত সুবিধা ছাড়াই
শন

1
... প্রক্রিয়া চলাকালীন ব্যবহৃত টেবিলগুলি লক না করেই ... কারণ এটি একটি কার্সারের অন্যতম সুবিধা :)
লেওনফো

3
টেবিল? এটি একটি টেবিল বৈকল্পিক - কোনও একযোগে অ্যাক্সেস সম্ভব নয়।
ডেনউকেম

ডেনউকেম, আপনি ঠিক বলেছেন, আমি মনে করি আমি যখন তখন এই প্রশ্নটি পড়ি তখন "ভেরিয়েবল" শব্দটি "এড়িয়ে গিয়েছিলাম" ... আমি আমার প্রাথমিক প্রতিক্রিয়ার সাথে কিছু নোট যুক্ত করব
লিওনফো

আমাকে ডেনউকেম এবং শনের সাথে একমত হতে হবে। কেন, কেন, আপনি কার্সার ব্যবহার এড়াতে এই দৈর্ঘ্যে কেন যান? আবার: তিনি একটি টেবিলের পরিবর্তনশীলটির মাধ্যমে পুনরাবৃত্তি করতে চান, traditionalতিহ্যবাহী টেবিল নয় !!!
পিটার

10

আপনার যদি FAST_FORWARD কার্সার তৈরি করে সারি সারি সারি করা ছাড়া কোনও উপায় না থাকে। এটি একটি দীর্ঘ লুপ তৈরির মতো দ্রুত এবং দীর্ঘ theালু রক্ষণাবেক্ষণ করা আরও সহজ হবে।

FAST_FORWARD একটি ফরওয়ার্ডপোটিয়ালি, READ_ONLY কার্সার পারফরম্যান্স অপটিমাইজেশন সক্ষম করে Spec যদি এসসিআরএল বা ফোর_আপডেও নির্দিষ্ট করা থাকে তবে FAST_FORWARD নির্দিষ্ট করা যায় না।


2
হ্যাঁ! আমি অন্য কোথাও মন্তব্য করার সাথে সাথে এখনও কোনও যুক্তি দেখতে পেলাম না যখন কেসটি টেবিলের ভেরিয়েবলের সাথে পুনরুক্তি করতে হবে তখন কার্সারটি কেন ব্যবহার করবেন না । একটি FAST_FORWARDকার্সর একটি সূক্ষ্ম সমাধান। (
upvote

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 (Select Count(*) From #TempTable) > 0
Begin
    Insert Into @Databases...

    Delete From #TempTable Where x = x
End

4

এটি এসকিউএল সার্ভার 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। কিন্তু এখানে অন্য বিকল্প যদি আপনি এসকিউএল সার্ভার সংস্করণ 2005/2008 ব্যবহার করছেন
ব্যবহারের Recursion

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

আমি যদি আপনার কোনও অনন্য আইডি থাকে তবে আপনি আপনার টেবিলটি বাছাই করতে পারেন:

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

এটি করতে কার্সার ব্যবহার করা সম্ভব:

ফাংশন তৈরি করুন [ডিবিও] .ফ_এটিস্ট_লুপ @ টবেলা টেবিলটি ফিরিয়ে দেয় (কোডড ইনট, নোম ভারচার (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;

শেষ

প্রক্রিয়া তৈরি করুন [ডিবিও]। [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

আমি পূর্ববর্তী পোস্টের সাথে একমত যে সেট-ভিত্তিক ক্রিয়াকলাপগুলি সাধারণত আরও ভাল সম্পাদন করবে, তবে আপনাকে যদি সারিগুলিতে পুনরাবৃত্তি করতে হয় তবে আমি যে পদ্ধতিটি গ্রহণ করব তা এখানে:

  1. আপনার টেবিল ভেরিয়েবলে একটি নতুন ক্ষেত্র যুক্ত করুন (ডেটা টাইপ বিট, ডিফল্ট 0)
  2. আপনার ডেটা .োকান
  3. শীর্ষ 1 সারিটি নির্বাচন করুন যেখানে fUsed = 0 (দ্রষ্টব্য: 1 ধাপে fUsed ক্ষেত্রের নাম)
  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 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

পদক্ষেপ 4: অস্থায়ী সারি সংখ্যার ভিত্তিতে লুপ টেম্প টেবিল তৈরি করুন

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

এই পদ্ধতির জন্য কেবল একটি পরিবর্তনশীল প্রয়োজন এবং @ ডেটাবেসগুলি থেকে কোনও সারি মুছবে না। আমি জানি যে এখানে প্রচুর উত্তর রয়েছে তবে আমি এটির মতো দেখতে পাচ্ছি না যা আপনার পরবর্তী আইডিটি পেতে এমআইএন ব্যবহার করে।

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

আমি ঠিক বুঝতে পেরেছি যে @ কন্ট্রোলফ্র্যাক আমার আগে এই পদ্ধতির প্রস্তাব দিয়েছে; আমি কেবল মন্তব্য এবং আরও একটি ভার্জোজ উদাহরণ যুক্ত করেছি।
মাস ডট নেট

0

এই কোডটি আমি ২০০৮ আর 2 ব্যবহার করছি। এই কোডটি আমি ব্যবহার করছি কী ক্ষেত্রগুলিতে সূচি তৈরি করতে (এসএসএনও এবং ইএমপিআর_এনও) 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

আপনি যদি রেফারেন্সিং টেবিলগুলি কেবলমাত্র মূল্য নির্ধারণ করে দিচ্ছেন তবে নির্বাচন নির্বাচন করুন Avo

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.