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

#6 Rodrigo Bedoya
08/08/2006 - 04:22 | Informe spam
Hola Alejandro y/o Maxi

Gracias por contestar pero la verdad , este problema se me volvio critico.
Tambien hice el cambio del atributo cursor global pero continua el error.
sp_dboption @dbname='dbadn',@optname='default to local
cursor',@optvalue='TRUE'

La razon por la que no puedo crear el cursor en forma directa , lo cual
funciona ,es por que mis tablas
son anuales (Cabecera2006,Cabecera2005 etc)

Declare cabecera CURSOR FOR SELECT ctransaccion FROM cabecera2006 where
cdocumento=@cdocumento and cnumero=@cnumero
Luego hago el open cabecera, y perfecto.

Al declararla en forma dinamica la creacion del cursor falla

SET @cExpresion="DECLARE cabecera CURSOR GLOBAL FOR SELECT cTransaccion FROM
cabecera"+@Cano+
" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
EXECUTE(@cExpresion)

Hago el OPen ... error
Msg 16958, Level 16, State 3, Procedure grabar, Line 34

No se pudo completar la operación de cursor porque las opciones establecidas
cambiaron desde que se declaró el cursor.



Lo que indica que el problema se da es por la expresion sql dinamico

Rodrigo
BOGOTA-COLOMBIA




"Rodrigo Bedoya" wrote in message
news:
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






Respuesta Responder a este mensaje
#7 Alejandro Mesa
08/08/2006 - 14:19 | Informe spam
Rodrigo,

Si solo usas este cursor para leer desde la tabla, entonces declaralo
tambien como FAST_FORWARD.

SET @cExpresion="
DECLARE cabecera CURSOR
GLOBAL
FAST_FORWARD
FOR
SELECT cTransaccion
FROM cabecera" + @Cano +
" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"

EXECUTE(@cExpresion)


De todas maneras te comento que no es necesario trabajar con un cursor
GLOBAL para hacer esto. Puedes usar el procedimiento sp_executesql para
devolver un cursor local en un parametro de salida. Te paso un ejemplo.

use northwind
go

select *
into dbo.orders_1997
from dbo.orders
where orderdate >= '19970101' and orderdate < '19980101'
go

select *
into dbo.orders_1998
from dbo.orders
where orderdate >= '19980101' and orderdate < '19990101'
go

create procedure dbo.p1
@year smallint
as
set nocount on

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

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

if object_id(@tn, 'U') is not null
begin
set @sql = 'set @c = cursor fast_forward for select orderid, orderdate 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 @orderid, @orderdate

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

select @orderid, @orderdate
end

close @c
deallocate @c
end
end
go

exec dbo.p1 1997
go

exec dbo.p1 1998
go

drop procedure dbo.p1
go

drop table dbo.orders_1997, dbo.orders_1998
go


AMB

"Rodrigo Bedoya" wrote:

Hola Alejandro y/o Maxi

Gracias por contestar pero la verdad , este problema se me volvio critico.
Tambien hice el cambio del atributo cursor global pero continua el error.
sp_dboption @dbname='dbadn',@optname='default to local
cursor',@optvalue='FALSE'

La razon por la que no puedo crear el cursor en forma directa , lo cual
funciona ,es por que mis tablas
son anuales (Cabecera2006,Cabecera2005 etc)

Declare cabecera CURSOR FOR SELECT ctransaccion FROM cabecera2006 where
cdocumento=@cdocumento and cnumero=@cnumero
Luego hago el open cabecera, y perfecto.

Al declararla en forma dinamica la creacion del cursor falla

SET @cExpresion="DECLARE cabecera CURSOR GLOBAL FOR SELECT cTransaccion FROM
cabecera"+@Cano+
" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
EXECUTE(@cExpresion)

Hago el OPen ... error
Msg 16958, Level 16, State 3, Procedure grabar, Line 34

No se pudo completar la operación de cursor porque las opciones establecidas
cambiaron desde que se declaró el cursor.



Lo que indica que el problema se da es por la expresion sql dinamico , algo
paso entre las versiones
2000 y 2005 que a un esta por resolver..

Gracias a todos , y quisiera que si pueden probar el script que he anexado
varias veces para alguno de ustedes puede vivirlo


RODRIGO






"Alejandro Mesa" wrote in message
news:
> Rodrigo,
>
> En SQL Server 2000 y 2005, existe una opcion a nivel de db, para
> especificar
> que tipo de cursor se crea (local o global) cuando esta opcion es omitida
> en
> la sentencia que declara el cursor (Fijate en la sentencia DECLARE que
> usas).
> El nombre de la opcion a nivel de db se llama "default to local cursor" y
> en
> la version 2000 es "false" por defecto, mientras que en la version 2005 es
> "true". Cuando declaras el cursor en el trigger:
>
>> SET @cExpresion="DECLARE cabecera CURSOR FOR SELECT cTransaccion FROM
>> cabecera"+@Cano+
>>
>> " WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
>>
>> EXECUTE(@cExpresion)
>
> SQL Server 2000 lo declara como global y por eso puedes abrirlo, hacer
> "fetch", etc. En cambio, en 2005 se esta declarando como "local" y por eso
> da
> error al referenciarlo en el trigger.
>
> La solucion es que declares el tipo de cursor explicitamente y que no
> bases
> tu programa en el comportamiento interno de SQL Server, o que cambies el
> valor de la opcion a nivel de database usando el procedimineto
> "sp_dboption"
> o la sentencia "alter database".
>
> SET @cExpresion="
> DECLARE cabecera CURSOR
> GLOBAL <-- BUENA PRACTICA
> FOR
> SELECT cTransaccion
> FROM cabecera" + @Cano +
> " WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
>
> EXECUTE(@cExpresion)
> ...
>
>
> AMB
>
>
> "Rodrigo Bedoya" wrote:
>
>> 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
>>
>>
>>
>>
>>
>>
>>



Respuesta Responder a este mensaje
#8 Rodrigo Bedoya
09/08/2006 - 05:42 | Informe spam
Gracias , seguire probando



"Rodrigo Bedoya" wrote in message
news:%

Hola Alejandro y/o Maxi

Gracias por contestar pero la verdad , este problema se me volvio critico.
Tambien hice el cambio del atributo cursor global pero continua el error.
sp_dboption @dbname='dbadn',@optname='default to local
cursor',@optvalue='TRUE'

La razon por la que no puedo crear el cursor en forma directa , lo cual
funciona ,es por que mis tablas
son anuales (Cabecera2006,Cabecera2005 etc)

Declare cabecera CURSOR FOR SELECT ctransaccion FROM cabecera2006 where
cdocumento=@cdocumento and cnumero=@cnumero
Luego hago el open cabecera, y perfecto.

Al declararla en forma dinamica la creacion del cursor falla

SET @cExpresion="DECLARE cabecera CURSOR GLOBAL FOR SELECT cTransaccion
FROM cabecera"+@Cano+
" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
EXECUTE(@cExpresion)

Hago el OPen ... error
Msg 16958, Level 16, State 3, Procedure grabar, Line 34

No se pudo completar la operación de cursor porque las opciones
establecidas cambiaron desde que se declaró el cursor.



Lo que indica que el problema se da es por la expresion sql dinamico

Rodrigo
BOGOTA-COLOMBIA




"Rodrigo Bedoya" wrote in message
news:
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










Respuesta Responder a este mensaje
#9 Rodrigo Bedoya
09/08/2006 - 06:03 | Informe spam
Gracias a todos ustedes que me han contestado.


El caso de cursores con sql dinamico funciona bien en procedimientos, pero
en triggers en la version sql2005 no.
Yo considero que debe haber un agujero en dicho punto . No puede ser que
algo tan elemental que venia funcionando en SQL2000 deje de funcionar sin
ninguna razon de fondo , se que hay cambios y debemos ajustarnos pero en
este punto falta por investigar..





"Rodrigo Bedoya" wrote in message
news:
Gracias , seguire probando



"Rodrigo Bedoya" wrote in message
news:%

Hola Alejandro y/o Maxi

Gracias por contestar pero la verdad , este problema se me volvio
critico.
Tambien hice el cambio del atributo cursor global pero continua el error.
sp_dboption @dbname='dbadn',@optname='default to local
cursor',@optvalue='TRUE'

La razon por la que no puedo crear el cursor en forma directa , lo cual
funciona ,es por que mis tablas
son anuales (Cabecera2006,Cabecera2005 etc)

Declare cabecera CURSOR FOR SELECT ctransaccion FROM cabecera2006 where
cdocumento=@cdocumento and cnumero=@cnumero
Luego hago el open cabecera, y perfecto.

Al declararla en forma dinamica la creacion del cursor falla

SET @cExpresion="DECLARE cabecera CURSOR GLOBAL FOR SELECT cTransaccion
FROM cabecera"+@Cano+
" WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
EXECUTE(@cExpresion)

Hago el OPen ... error
Msg 16958, Level 16, State 3, Procedure grabar, Line 34

No se pudo completar la operación de cursor porque las opciones
establecidas cambiaron desde que se declaró el cursor.



Lo que indica que el problema se da es por la expresion sql dinamico

Rodrigo
BOGOTA-COLOMBIA




"Rodrigo Bedoya" wrote in message
news:
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














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

Pudieras postear la ultima version que has probado y cual es el mensaje de
error que te da?


AMB


"Rodrigo Bedoya" wrote:

Gracias a todos ustedes que me han contestado.


El caso de cursores con sql dinamico funciona bien en procedimientos, pero
en triggers en la version sql2005 no.
Yo considero que debe haber un agujero en dicho punto . No puede ser que
algo tan elemental que venia funcionando en SQL2000 deje de funcionar sin
ninguna razon de fondo , se que hay cambios y debemos ajustarnos pero en
este punto falta por investigar..





"Rodrigo Bedoya" wrote in message
news:
> Gracias , seguire probando
>
>
>
> "Rodrigo Bedoya" wrote in message
> news:%
>>
>> Hola Alejandro y/o Maxi
>>
>> Gracias por contestar pero la verdad , este problema se me volvio
>> critico.
>> Tambien hice el cambio del atributo cursor global pero continua el error.
>> sp_dboption @dbname='dbadn',@optname='default to local
>> cursor',@optvalue='TRUE'
>>
>> La razon por la que no puedo crear el cursor en forma directa , lo cual
>> funciona ,es por que mis tablas
>> son anuales (Cabecera2006,Cabecera2005 etc)
>>
>> Declare cabecera CURSOR FOR SELECT ctransaccion FROM cabecera2006 where
>> cdocumento=@cdocumento and cnumero=@cnumero
>> Luego hago el open cabecera, y perfecto.
>>
>> Al declararla en forma dinamica la creacion del cursor falla
>>
>> SET @cExpresion="DECLARE cabecera CURSOR GLOBAL FOR SELECT cTransaccion
>> FROM cabecera"+@Cano+
>> " WHERE cDocumento='"+@cDOCUMENTO+"' AND cNumero='"+@cNumero+"'"
>> EXECUTE(@cExpresion)
>>
>> Hago el OPen ... error
>> Msg 16958, Level 16, State 3, Procedure grabar, Line 34
>>
>> No se pudo completar la operación de cursor porque las opciones
>> establecidas cambiaron desde que se declaró el cursor.
>>
>>
>>
>> Lo que indica que el problema se da es por la expresion sql dinamico
>>
>> Rodrigo
>> BOGOTA-COLOMBIA
>>
>>
>>
>>
>> "Rodrigo Bedoya" wrote in message
>> news:
>>> 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
>>>
>>>
>>>
>>>
>>>
>>>
>>
>>
>
>



Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida