Microsoft quito el soporte de cursores en triggesr??

07/08/2006 - 15:35 por Rodrigo Bedoya | Informe spam
Tengo Una aplicacion bastante robusta y estable en sql2000, pero algunos
clientes pequeños van a tener sql2005 express , mi pregunta es microsoft
quito el soporte de cursores en triggers cuando se ejecutan dinamicamente en
cadenas ?? .. Anexo este ejemplo sencillo pero completo donde se crea un
cursor en un trigger

/*

En este paquete se crean las tablas cabecera2006 y detalle2006

El trigger asociado a la tabla de detalle

Se graba un registro en cabecera y otro en detalle para visualizar el

el error en sql2005 , pero este mismo paquete se corre en sql2000 bien.

*/






GO

- Archivo Detalle --

CREATE TABLE DETALLE2006(

[cDocumento] [char](2) DEFAULT (' '),

[cNumero] [char](8) DEFAULT (' '),

[dFecha] [datetime] DEFAULT (' '),

[cTERCERO] [char](11) DEFAULT (' '),

[ccuenta] [char](20) DEFAULT (' '),

[nValor] numeric(10,2) DEFAULT (0),

[nItem] int DEFAULT (0),

CONSTRAINT [DETALLE2006_] PRIMARY KEY NONCLUSTERED

(

[cDOCUMENTO] ASC,

[cNumero] ASC,

[nItem] ASC

)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]

GO

DROP TABLE CABECERA2006

GO

-Archivo Cabecera

CREATE TABLE CABECERA2006(

[cDocumento] [char](2) DEFAULT (' '),

[cNumero] [char](8) DEFAULT (' '),

[dFecha] [datetime] DEFAULT (' '),

[cTransaccion] [char] (10) DEFAULT (' '),

CONSTRAINT [CABECERA2006_] PRIMARY KEY NONCLUSTERED

(

[cDOCUMENTO] ASC,

[cNumero] ASC

)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]

GO

Trigger Tabla Detalle

set ANSI_NULLS ON

set QUOTED_IDENTIFIER OFF

GO

CREATE TRIGGER [dbo].[grabacion] ON [dbo].[DETALLE2006]

FOR INSERT

AS

DECLARE @Cdocumento CHAR(2),

@cNumero CHAR(8),

@dFecha DATETIME,

@cExpresion VARCHAR(200),

@cTransaccion CHAR(10),

@cAno CHAR(4)

SELECT @cDocumento = ins.cDocumento,@cNumero = ins.cNumero,@dFecha =
ins.dFecha FROM INSERTED INS

SET @Cano = LTRIM(RTRIM(STR(YEAR(@dFecha))))

Dependiendo de la fecha se carga la tabla respectiva pueder ser

cabecera2005, cabecera2006 etc, por eso se hace en forma dinamica

SET @cExpresion="DECLARE cabecera CURSOR FOR SELECT cTransaccion FROM
cabecera"+@Cano+

" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"

EXECUTE(@cExpresion)

Solo es un ejemplo para traer datos de la cabecera y aplicar

algun logica en el trigger

OPEN cabecera

FETCH NEXT FROM cabecera INTO @cTransaccion

CLOSE cabecera

DEALLOCATE cabecera






RETURN

Insertamos Registro Cabecera -

INSERT INTO CABECERA2006 VALUES('RC','9898','05/08/2006','COMPRAS')

GO

/*

Insertamos Registro Detalle

Aqui se ejecuta el trigger de insertar de la tabla detalle2006

y se genera error ,pero en sql2000 no genera error

*/

INSERT INTO DETALLE2006
VALUES('RC','9898','05/08/2006','7528558','1305050',1500000,1);

Todo Esto Funciona super bien en sql2000



Saludos



RODRIGO

Preguntas similare

Leer las respuestas

#11 Rodrigo Bedoya
10/08/2006 - 05:39 | Informe spam
Hola alejandro , el tema se puede replicar creando un cursor con sql
dinamicamente (Es decir en Cadenas)
cualquiere en un trigger y tratar de hacer el open del cursor alli falla .
Probe tu recomendacion y funciona en un procedimiento pero dentro triiger
falla.

Gracias

Anexo ultimo trigger

set ANSI_NULLS ON

set QUOTED_IDENTIFIER OFF

GO



ALTER TRIGGER [dbo].[grabar] ON [dbo].[MOVD2006]

FOR INSERT

AS



DECLARE @DOCUMENTO CHAR(2),

@NUMERO_CPB CHAR(8),

@LcSql nVARCHAR(200),

@ano CHAR(4),

@LcPar nVARCHAR(200),

@oper_crea char(10)


SELECT @DOCUMENTO= ins.documento,

@NUMERO_CPB= ins.numero_cpb,

@ano=convert(char(4),YEAR(MDE_FEHCPB)) FROM INSERTED INS;

Se declara dinamicamente por que el nombre de la tabla

se sabe solo con el ano MOVG"+@ano

SET @LcSql=N'DECLARE cabecera CURSOR fast_forward GLOBAL FOR SELECT
OPER_CREA FROM MOVG'+@ano+

' WHERE DOCUMENTO=@par1 AND NUMERO_CPB=@par2';

SET @LcPar=N'@par1 CHAR(2),@par2 CHAR(8)';

Al ejecutar la instruccion siguiente no se esta generando el cursor

Esto mismo en SQL 2000 funciona correctamente , pero en SQL 2005 genera
error

por que no se tiene el cursor

/*

exec sp_executesql @LcSql,@LcPar,@Documento,@numero_cpb





OPEN cabecera;

FETCH NEXT FROM cabecera INTO @oper_crea

print @oper_crea

CLOSE cabecera;

DEALLOCATE cabecera;



- Continua el trigger - metodo de alejandro -

declare @c cursor

declare @sql nvarchar(4000)

declare @tn sysname

declare @year smallint

set @year97

set @year = coalesce(@year, year(getdate()))

set @tn = N'dbo.orders_' + ltrim(@year)

PRINT @tn

if object_id(@tn, 'U') is not null

begin

PRINT 'RODRIGO'

set @sql = 'set @c = cursor fast_forward for select DOCUMENTO, NUMERO_CPB
from

' + @tn + N' open @c'

exec dbo.sp_executesql @sql, N'@c cursor output', @c output

if cursor_status('variable', '@c') = 1

begin

while 1 = 1

begin

fetch next from @c into @documento, @numero_cpb

if @@error != 0 or @@fetch_status != 0 break

select @documento, @numero_cpb

print @documento

end

end

end



/* Se Genera el siguiente error

Msg 16958, Level 16, State 3, Procedure grabar, Line 31

No se pudo completar la operación de cursor porque las opciones establecidas

cambiaron desde que se declaró el cursor.

*/



RETURN
Respuesta Responder a este mensaje
#12 Alejandro Mesa
10/08/2006 - 14:07 | Informe spam
Rodrigo,

Se me paso declarar el cursor como LOCAL

- Continua el trigger - metodo de alejandro -
declare @c cursor
declare @sql nvarchar(4000)
declare @tn sysname
declare @year smallint

set @year97
set @year = coalesce(@year, year(getdate()))
set @tn = N'dbo.orders_' + ltrim(@year)

PRINT @tn

if object_id(@tn, 'U') is not null
begin
PRINT 'RODRIGO'

set @sql = 'set @c = cursor fast_forward for select DOCUMENTO, NUMERO_CPB
from

' + @tn + N' open @c'



set @sql = '
set @c = cursor LOCAL fast_forward for
select DOCUMENTO, NUMERO_CPB
from ' + @tn + N' open @c'


Esta es la version modificada.

ALTER TRIGGER [dbo].[grabar] ON [dbo].[MOVD2006]
FOR INSERT
AS

DECLARE @DOCUMENTO CHAR(2),
@NUMERO_CPB CHAR(8),
@LcSql nVARCHAR(200),
@ano CHAR(4),
@LcPar nVARCHAR(200),
@oper_crea char(10)

declare @c cursor

SELECT
@DOCUMENTO = ins.documento,
@NUMERO_CPB = ins.numero_cpb,
@ano = convert(char(4),YEAR(MDE_FEHCPB))
FROM
INSERTED

Se declara dinamicamente por que el nombre de la tabla
se sabe solo con el ano MOVG"+@ano

SET @LcSql=N'
set @c = CURSOR local fast_forward FOR
SELECT OPER_CREA
FROM MOVG'+ @ano + N' WHERE DOCUMENTO=@par1 AND NUMERO_CPB=@par2; open @c';

SET @LcPar = N'@par1 CHAR(2),@par2 CHAR(8),@c cursor output';

exec dbo.sp_executesql @LcSql,@LcPar,@Documento,@numero_cpb, @c output

if cursor_status('variable', '@c') = 1
begin
FETCH NEXT FROM @c INTO @oper_crea

print @oper_crea

CLOSE @c

DEALLOCATE @c
end
GO


AMB

"Rodrigo Bedoya" wrote:

Hola alejandro , el tema se puede replicar creando un cursor con sql
dinamicamente (Es decir en Cadenas)
cualquiere en un trigger y tratar de hacer el open del cursor alli falla .
Probe tu recomendacion y funciona en un procedimiento pero dentro triiger
falla.

Gracias

Anexo ultimo trigger

set ANSI_NULLS ON

set QUOTED_IDENTIFIER OFF

GO



ALTER TRIGGER [dbo].[grabar] ON [dbo].[MOVD2006]

FOR INSERT

AS



DECLARE @DOCUMENTO CHAR(2),

@NUMERO_CPB CHAR(8),

@LcSql nVARCHAR(200),

@ano CHAR(4),

@LcPar nVARCHAR(200),

@oper_crea char(10)


SELECT @DOCUMENTO= ins.documento,

@NUMERO_CPB= ins.numero_cpb,

@ano=convert(char(4),YEAR(MDE_FEHCPB)) FROM INSERTED INS;

Se declara dinamicamente por que el nombre de la tabla

se sabe solo con el ano MOVG"+@ano

SET @LcSql=N'DECLARE cabecera CURSOR fast_forward GLOBAL FOR SELECT
OPER_CREA FROM MOVG'+@ano+

' WHERE DOCUMENTO=@par1 AND NUMERO_CPB=@par2';

SET @LcPar=N'@par1 CHAR(2),@par2 CHAR(8)';

Al ejecutar la instruccion siguiente no se esta generando el cursor

Esto mismo en SQL 2000 funciona correctamente , pero en SQL 2005 genera
error

por que no se tiene el cursor

/*

exec sp_executesql @LcSql,@LcPar,@Documento,@numero_cpb





OPEN cabecera;

FETCH NEXT FROM cabecera INTO @oper_crea

print @oper_crea

CLOSE cabecera;

DEALLOCATE cabecera;



- Continua el trigger - metodo de alejandro -

declare @c cursor

declare @sql nvarchar(4000)

declare @tn sysname

declare @year smallint

set @year97

set @year = coalesce(@year, year(getdate()))

set @tn = N'dbo.orders_' + ltrim(@year)

PRINT @tn

if object_id(@tn, 'U') is not null

begin

PRINT 'RODRIGO'

set @sql = 'set @c = cursor fast_forward for select DOCUMENTO, NUMERO_CPB
from

' + @tn + N' open @c'

exec dbo.sp_executesql @sql, N'@c cursor output', @c output

if cursor_status('variable', '@c') = 1

begin

while 1 = 1

begin

fetch next from @c into @documento, @numero_cpb

if @@error != 0 or @@fetch_status != 0 break

select @documento, @numero_cpb

print @documento

end

end

end



/* Se Genera el siguiente error

Msg 16958, Level 16, State 3, Procedure grabar, Line 31

No se pudo completar la operación de cursor porque las opciones establecidas

cambiaron desde que se declaró el cursor.

*/



RETURN































































Respuesta Responder a este mensaje
#13 Rodrigo Bedoya
11/08/2006 - 05:28 | Informe spam
Hola alejandro

Continua el error, la unica alternativa que tengo es volver las tablas de
cabecera infinitas para poder crear el cursor
directamente sin sintaxis sql dinamico, pero me queda la duda por que falla
esta situacion de cursores en triggers

Muchas Gracias de tu Parte

Rodrigo Bedoya Z.
Bogota - Colombia

Nota : Cuando hacer pruebas las ha ejecutado dentro de un triggers ?
Respuesta Responder a este mensaje
#14 Alejandro Mesa
11/08/2006 - 15:17 | Informe spam
rodrigo,

verdad que no he tratado de reproducir el problema, pues no tengo instalado
SQL Server 2005 en la computer con la que trabajo. Tratare de hacerlo en casa
durante el fin de semana.

Por lo pronto te recomiendo ver la posibilidad de usar una vista particionada.

Using Partitioned Views
http://msdn2.microsoft.com/en-us/li...90019.aspx


AMB

"Rodrigo Bedoya" wrote:

Hola alejandro

Continua el error, la unica alternativa que tengo es volver las tablas de
cabecera infinitas para poder crear el cursor
directamente sin sintaxis sql dinamico, pero me queda la duda por que falla
esta situacion de cursores en triggers

Muchas Gracias de tu Parte

Rodrigo Bedoya Z.
Bogota - Colombia

Nota : Cuando hacer pruebas las ha ejecutado dentro de un triggers ?





Respuesta Responder a este mensaje
#15 Alejandro Mesa
13/08/2006 - 01:02 | Informe spam
Rodrigo,

Encontre la forma de que trabaje, pero no encontre la respuesta logica.
Usando el mismo codigo que posteastes en tu primer post, declare el cursor
como:

GLOBAL
FORWARD_ONLY
STATIC

SET @cExpresion="DECLARE cabecera CURSOR FOR SELECT cTransaccion



SET @cExpresion = 'DECLARE cabecera CURSOR
GLOBAL
FORWARD_ONLY
STATIC
FOR SELECT cTransaccion
...'

Tambien puedes usar la version que usa sp_executesql, donde lo declares
LOCAL en vez de GLOBAL. Este ejemplo funciona en 2005.

use adventureworks
go

create table dbo.t1 (
c1 int not null identity(1, 1)
)
go

create trigger tr_t1_ins on dbo.t1
for insert
as

declare @orderid int
declare @orderdate datetime
declare @c cursor
declare @sql nvarchar(4000)
declare @i int

set @i = (select max(c1) from inserted)

set @sql = N'set @c = cursor LOCAL FORWARD_ONLY STATIC FOR '

if @i % 2 != 0
set @sql = @sql + 'select top 1 salesorderid, orderdate from
AdventureWorks.Sales.SalesOrderHeader'
else
set @sql = @sql + 'select top 1 purchaseorderid, orderdate from
AdventureWorks.Purchasing.PurchaseOrderHeader'

set @sql = @sql + ';open @c'

exec dbo.sp_executesql @sql, N'@c cursor output', @c output

if cursor_status('variable', '@c') = 1
begin
while 1 = 1
begin

fetch next from @c into @orderid, @orderdate

if @@error != 0 or @@fetch_status != 0 break

select @orderid, @orderdate

end

close @c
deallocate @c
end
go

insert into dbo.t1 default values
go

drop table dbo.t1
go


Saludos,

Alejandro
AMB

"Alejandro Mesa" wrote:

rodrigo,

verdad que no he tratado de reproducir el problema, pues no tengo instalado
SQL Server 2005 en la computer con la que trabajo. Tratare de hacerlo en casa
durante el fin de semana.

Por lo pronto te recomiendo ver la posibilidad de usar una vista particionada.

Using Partitioned Views
http://msdn2.microsoft.com/en-us/li...90019.aspx


AMB

"Rodrigo Bedoya" wrote:

> Hola alejandro
>
> Continua el error, la unica alternativa que tengo es volver las tablas de
> cabecera infinitas para poder crear el cursor
> directamente sin sintaxis sql dinamico, pero me queda la duda por que falla
> esta situacion de cursores en triggers
>
> Muchas Gracias de tu Parte
>
> Rodrigo Bedoya Z.
> Bogota - Colombia
>
> Nota : Cuando hacer pruebas las ha ejecutado dentro de un triggers ?
>
>
>
>
>
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida