Urgente. Script con cursor que funciona el 2005 y no en 2000.

12/01/2007 - 11:24 por Salvador Ramos | Informe spam
Hola a todos,

En primer lugar perdona por indicar urgente, pero es que voy contra-reloj en
un proyecto, y ahora me surge un problema que no logro ver.

Tras llevar un tiempo probando este script en SQL Server 2005, ahora
necesito ejecutarlo en SQL Server 2000, y me he llevado la sorpresa de que
me da el siguiente error:

Mens. 16929, Nivel 16, Estado 1, Línea 15
El cursor es READ ONLY.
Se terminó la instrucción.

Además no tengo la aydua de SQL Server 2000, si alguien me puede indicar
cual es el problema le estaré muy agradecido.

declare @Id int, @PK char(75), @PKant char(75), @dup int
declare CurDuplicados cursor local forward_only
for select Id, PK
from tmpGasoleoProf01
where PK in(select PK from dbo.tmpGasoleoProf01
group by PK having count(*) > 1)
order by PK
open CurDuplicados
fetch next from CurDuplicados into @Id, @PK
while @@fetch_status = 0 begin
set @PKant = @PK
set @dup = 0
while @@fetch_status = 0 and @PK = @PKant begin
set @dup = @dup + 1
update tmpGasoleoProf01
set PK = left(@PK, 73) + right(rtrim('00' + cast(@dup as char(2))), 2)
where current of CurDuplicados
fetch next from CurDuplicados into @Id, @PK
end
end
close CurDuplicados
deallocate CurDuplicados

Además este otro cursor, que en principio es igual si que me funciona en
2005 y 2000:

declare @PK char(75), @Hora char(4)
declare CurHora cursor local forward_only
for select PK, hora
from tmpGasoleoProf01
where hora = ''
open CurHora
fetch next from CurHora into @PK, @Hora
while @@fetch_status = 0 begin
update tmpGasoleoProf01
set Hora = right(rtrim('00' + cast(cast( RAND() * 24 as int) as char(2))),
2) +
right(rtrim('00' + cast(cast( RAND() * 60 as int) as char(2))), 2)
where current of CurHora
fetch next from CurHora into @PK, @Hora
end
close CurHora
deallocate CurHora

Por qué el primero funciona en 2005 y no en 2000 y el segundo funciona bien
en 2005 y 2000, cuando son iguales (salvo que hacen actualizaciones
diferentes) ?

Muchas gracias

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net

Preguntas similare

Leer las respuestas

#6 Liliana Sorrentino
18/01/2007 - 14:47 | Informe spam
:-)

"Salvador Ramos" escribió en el
mensaje news:
Muchas gracias Liliana,

Es un placer leerte de nuevo por aquí :-)

Perdón por la tardanza en mi respuesta, es que he tenido que estar fuera
unos días.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net


"Liliana Sorrentino" escribió en el
mensaje news:
Hola Salvador,
A riesgo de que Miguel E. me quite la membresía de la brigada
anticursores, hice algunas pruebas con tu código...
La subconsulta de la primera actualización tiene un GROUP BY, y según los
BOL (2000) en "Conversiones de cursor implícitas", eso lo convierte en
Estático, ese es uno de los motivo.
El otro es el ORDER BY, que si bien no lo veo en los BOL, una viejísima y
lamentable experiencia propia me lo recuerda.
Verás que, definiendo una tabla extra con tu subconsulta, y sin ordenar
los datos, funciona bien.

Saludos,
Liliana.

"Salvador Ramos" escribió en el
mensaje news:
Muchas gracias por tu pronta respuesta.

La verdad que a pesar de ser esa la diferencia, no entiendo por qué me
indica que el cursor es READ ONLY cuando realmente estoy usando el mismo
tipo de cursor en ambos casos. No veo en qué puede influir el que haya
una subselect.

Seguiremos investigando ...

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net


"J.A. García Barceló" escribió en el mensaje
news:%
Me refiero a que está en un subselect: ambos casos tienen el campo que
posteriormente se va a actualizar en la cláusula where, pero sólo la
primera tiene un subselect.

J.A. García Barceló
http://jagbarcelo.blogspot.com


"J.A. García Barceló" escribió en el
mensaje news:%
Yo tampoco tengo ahora SQL 2000 instalado pero así, a simple vista veo
lo siguiente:

El cursor definido en tu primer caso es:

declare CurDuplicados cursor local forward_only
for select Id, PK
from tmpGasoleoProf01
where PK in(select PK from dbo.tmpGasoleoProf01
group by PK having count(*) > 1)

Estas usando como filtro (.. where PK in...) el campo que
posteiormente vas a actualizar (update ... set PK ...). Básicamente
esa es la única diferencia que veo entre los dos casos que presentas.
Tal vez tengas que declarar el cursor en el primer caso con alguna
opcion como:

STATIC

Define un cursor que hace una copia temporal de los datos que va a
utilizar. Todas las solicitudes que se realizan al cursor se responden
desde esta tabla temporal de tempdb; por tanto, las modificaciones
realizadas en las tablas base no se reflejan en los datos devueltos
por las operaciones de recuperación realizadas en el cursor y [además
este cursor no admite modificaciones]

Fíjate que aunque al final dice que no admite modificaciones, tu no
vas a modificar el cursor, sino una tabla subyacente. Tampoco se si
esta opción está disponible en SQL 2000 esto es de los BOL de 2005
pero igual te sirve para empezar o plantearte el cursor de algun otro
modo.

Un saludo.


J.A. García Barceló
http://jagbarcelo.blogspot.com

"Salvador Ramos" escribió en el
mensaje news:
Hola a todos,

En primer lugar perdona por indicar urgente, pero es que voy
contra-reloj en un proyecto, y ahora me surge un problema que no
logro ver.

Tras llevar un tiempo probando este script en SQL Server 2005, ahora
necesito ejecutarlo en SQL Server 2000, y me he llevado la sorpresa
de que me da el siguiente error:

Mens. 16929, Nivel 16, Estado 1, Línea 15
El cursor es READ ONLY.
Se terminó la instrucción.

Además no tengo la aydua de SQL Server 2000, si alguien me puede
indicar cual es el problema le estaré muy agradecido.

declare @Id int, @PK char(75), @PKant char(75), @dup int
declare CurDuplicados cursor local forward_only
for select Id, PK
from tmpGasoleoProf01
where PK in(select PK from dbo.tmpGasoleoProf01
group by PK having count(*) > 1)
order by PK
open CurDuplicados
fetch next from CurDuplicados into @Id, @PK
while @@fetch_status = 0 begin
set @PKant = @PK
set @dup = 0
while @@fetch_status = 0 and @PK = @PKant begin
set @dup = @dup + 1
update tmpGasoleoProf01
set PK = left(@PK, 73) + right(rtrim('00' + cast(@dup as char(2))),
2)
where current of CurDuplicados
fetch next from CurDuplicados into @Id, @PK
end
end
close CurDuplicados
deallocate CurDuplicados

Además este otro cursor, que en principio es igual si que me funciona
en 2005 y 2000:

declare @PK char(75), @Hora char(4)
declare CurHora cursor local forward_only
for select PK, hora
from tmpGasoleoProf01
where hora = ''
open CurHora
fetch next from CurHora into @PK, @Hora
while @@fetch_status = 0 begin
update tmpGasoleoProf01
set Hora = right(rtrim('00' + cast(cast( RAND() * 24 as int) as
char(2))), 2) +
right(rtrim('00' + cast(cast( RAND() * 60 as int) as char(2))), 2)
where current of CurHora
fetch next from CurHora into @PK, @Hora
end
close CurHora
deallocate CurHora

Por qué el primero funciona en 2005 y no en 2000 y el segundo
funciona bien en 2005 y 2000, cuando son iguales (salvo que hacen
actualizaciones diferentes) ?

Muchas gracias

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net























Respuesta Responder a este mensaje
#7 Salvador Ramos
18/01/2007 - 18:36 | Informe spam
Hola Alejandro,

En primer lugar perdon por mi tardanza en la respuesta, pero he estado fuera
unos días.

He intentado probar tu primera solución, y me indica que no puedo
especificar FOR UPDATE al ser un cursor READ ONLY (se convierte en read only
por lo que me ha indicado Liliana).

Finalmente he utilizado la segunda propuesta, que además elimina el cursor y
funciona perfectamente (salvo un par de mínimos errores de sintaxis sin
ninguna importancia al escribir el código, donde pone @pk debe poner pk, y
donde pone cpk también debe poner pk), así es como quedó:

update dbo.tmpGasoleoProf01
set pk = left(PK, 73) + right(rtrim('00' + cast((select count(*)
from dbo.tmpGasoleoProf01 as a
where a.pk = dbo.tmpGasoleoProf01.pk
and a.[Id] <= dbo.tmpGasoleoProf01.[Id]
) as char(2))), 2)
where exists(select *
from dbo.tmpGasoleoProf01 as b
where b.[Id] != dbo.tmpGasoleoProf01.[Id]
and b.pk = dbo.tmpGasoleoProf01.pk
)
go

Muchas gracias.

Pd. La brigada anticursores también te lo agradecerá ;-)

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net


"Alejandro Mesa" escribió en el
mensaje news:
Salvador,

Cuando queremos actualizar usando un cursor, se debe usar la clausula "[
FOR
UPDATE [ OF column_name [ ,...n ] ] ]".

declare CurDuplicados cursor local forward_only
for select Id, PK
from tmpGasoleoProf01
where PK in(select PK from dbo.tmpGasoleoProf01
group by PK having count(*) > 1)
order by PK
FOR UPDATE OF [PK]

Tengo una pregunta, es la columna [Id] unique en esa tabla?

De ser asi, creo que puedes cambiar ese cursor por:

update
dbo.tmpGasoleoProf01
set pk = left(@PK, 73) + right(rtrim('00' + cast(
(
select
count(*)
from
dbo.tmpGasoleoProf01 as a
where
a.cpk = dbotmpGasoleoProf01.pk
and a.[Id] <= dbo.tmpGasoleoProf01.[Id]
)
as char(2))), 2)
where
exists (
select
*
from
dbo.tmpGasoleoProf01 as b
where
b.[Id] != dbo.tmpGasoleoProf01.[Id]
and b.pk = dbo.tmpGasoleoProf01.pk
)
go


Saludos,

AMB


"Salvador Ramos" wrote:

Hola a todos,

En primer lugar perdona por indicar urgente, pero es que voy contra-reloj
en
un proyecto, y ahora me surge un problema que no logro ver.

Tras llevar un tiempo probando este script en SQL Server 2005, ahora
necesito ejecutarlo en SQL Server 2000, y me he llevado la sorpresa de
que
me da el siguiente error:

Mens. 16929, Nivel 16, Estado 1, Línea 15
El cursor es READ ONLY.
Se terminó la instrucción.

Además no tengo la aydua de SQL Server 2000, si alguien me puede indicar
cual es el problema le estaré muy agradecido.

declare @Id int, @PK char(75), @PKant char(75), @dup int
declare CurDuplicados cursor local forward_only
for select Id, PK
from tmpGasoleoProf01
where PK in(select PK from dbo.tmpGasoleoProf01
group by PK having count(*) > 1)
order by PK
open CurDuplicados
fetch next from CurDuplicados into @Id, @PK
while @@fetch_status = 0 begin
set @PKant = @PK
set @dup = 0
while @@fetch_status = 0 and @PK = @PKant begin
set @dup = @dup + 1
update tmpGasoleoProf01
set PK = left(@PK, 73) + right(rtrim('00' + cast(@dup as char(2))), 2)
where current of CurDuplicados
fetch next from CurDuplicados into @Id, @PK
end
end
close CurDuplicados
deallocate CurDuplicados

Además este otro cursor, que en principio es igual si que me funciona en
2005 y 2000:

declare @PK char(75), @Hora char(4)
declare CurHora cursor local forward_only
for select PK, hora
from tmpGasoleoProf01
where hora = ''
open CurHora
fetch next from CurHora into @PK, @Hora
while @@fetch_status = 0 begin
update tmpGasoleoProf01
set Hora = right(rtrim('00' + cast(cast( RAND() * 24 as int) as
char(2))),
2) +
right(rtrim('00' + cast(cast( RAND() * 60 as int) as char(2))), 2)
where current of CurHora
fetch next from CurHora into @PK, @Hora
end
close CurHora
deallocate CurHora

Por qué el primero funciona en 2005 y no en 2000 y el segundo funciona
bien
en 2005 y 2000, cuando son iguales (salvo que hacen actualizaciones
diferentes) ?

Muchas gracias

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server / MCTS: SQL Server 2005]
www.helpdna.net (información sobre SQL Server y .NET)
Y ahora también en www.sqlserverymicrosoft.net




email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida