I'm facing one of those situations where I need to perform an action for each row resulting from a query.
In this way I have two options, to use a Cursor
or a Table Variable
, however the two seem to me very similar (semantically).
I'd like to know if using Table Variable
will get some performance improvement over Cursor
.
I believe the difference between the two is that Table Variable
will only perform a query and scroll through the records in memory, whereas Cursor
will perform a query ( Fetch
) for each row, but not% I have to confirm (this my objection).
So which one is better and why?
EDIT
I decided to add a complete example and the statistics.
TABLE
CREATE TABLE [dbo].[CursorTeste](
[CursorTesteID] [int] IDENTITY(1,1) NOT NULL,
[Coluna1] [uniqueidentifier] NOT NULL,
[Coluna2] [uniqueidentifier] NOT NULL,
[Coluna3] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_CursorTeste] PRIMARY KEY CLUSTERED
(
[CursorTesteID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT
DECLARE @count int;
SET @count = 0;
WHILE (@count < 10000)
BEGIN
INSERT INTO CursorTeste VALUES (NEWID(), NEWID(), NEWID());
SET @count = @count + 1;
END
CURSOR
DECLARE @coluna1 uniqueidentifier;
DECLARE @coluna2 uniqueidentifier;
DECLARE @coluna3 uniqueidentifier;
DECLARE @CURSOR_teste CURSOR;
SET @CURSOR_teste = CURSOR LOCAL FAST_FORWARD FOR
SELECT Coluna1, Coluna2, Coluna3 FROM CursorTeste
OPEN @CURSOR_teste
WHILE (1 = 1)
BEGIN
FETCH NEXT FROM @CURSOR_teste INTO @coluna1, @coluna2, @coluna3;
IF (@@FETCH_STATUS <> 0)
BEGIN
BREAK;
END
PRINT '{ ' + cast(@coluna1 as varchar(50)) + ' } - { ' + cast(@coluna2 as varchar(50)) + ' } - { ' + cast(@coluna3 as varchar(50)) + ' }';
END
CLOSE @CURSOR_teste
DEALLOCATE @CURSOR_teste
Table Variable
DECLARE @coluna1 uniqueidentifier;
DECLARE @coluna2 uniqueidentifier;
DECLARE @coluna3 uniqueidentifier;
DECLARE @indice int
DECLARE @count int
DECLARE @tabela table(
RowNumber int identity,
Coluna1 uniqueidentifier not null,
Coluna2 uniqueidentifier not null,
Coluna3 uniqueidentifier not null,
PRIMARY KEY (RowNumber)
);
INSERT INTO @tabela
SELECT Coluna1, Coluna2, Coluna3 FROM CursorTeste
SET @count = (SELECT COUNT(RowNumber) FROM @tabela)
SET @indice = 1;
WHILE (@indice <= @count)
BEGIN
SELECT
@indice = RowNumber + 1,
@coluna1 = Coluna1,
@coluna2 = Coluna2,
@coluna3 = Coluna3
FROM @tabela
WHERE RowNumber = @indice
PRINT '{ ' + cast(@coluna1 as varchar(50)) + ' } - { ' + cast(@coluna2 as varchar(50)) + ' } - { ' + cast(@coluna3 as varchar(50)) + ' }';
END
- Evaluation 1: CURSOR
- Evaluation 2: CURSOR FAST_FORWARD
- Evaluation 3: FAST_FORWARD LOCAL CURSOR
- Rating 4: WHILE LOOP WITH @TABLE