me gustaría ejecutar un procedimiento almacenado sobre cada fila en un conjunto sin necesidad de utilizar un cursor con algo como esto:
SELECT EXEC dbo.Sproc @Param1 = Table1.id
FROM Table1
Estoy usando T-SQL en SQL Server 2005. Creo que esto podría ser posible usando una función, pero me gustaría usar un procedimiento almacenado si es posible (estándares de la compañía)¿Es posible ejecutar un procedimiento almacenado en un conjunto sin utilizar un cursor?
Respuesta
9 de cada 10 veces puede hacer lo que quiera sin un cursor o un ciclo while. Sin embargo, si debe usar uno, he encontrado que aunque los bucles tienden a ser más rápidos.
Además, si usted no desea borrar o actualizar la tabla, se puede usar algo como esto:
DECLARE @id [type]
SELECT @id = MIN([id]) FROM [table]
WHILE @id IS NOT NULL
BEGIN
EXEC [sproc] @id
SELECT @id = MIN([id]) FROM [table] WHERE [id] > @id
END
Sí. Si usted tiene una columna se puede utilizar dentro de la tabla para marcar los procesados, puede utilizar mientras exista:
DECLARE @Id int
WHILE EXISTS(SELECT * FROM Table1 WHERE Processed='N')
BEGIN
SELECT Top 1 @Id = id from Table1 WHERE Procesed='N'
EXEC dbo.Sproc @Id
UPDATE Table1 SET Processed = 'Y' WHERE Id = @Id
END
Alternativamente, volcar los identificadores en una variable de tabla temporal o mesa y eliminar cuando haya terminado:
DECLARE @HoldTable table (Id int PRIMARY KEY)
DECLARE @Id int
INSERT INTO @HoldTable SELECT Id FROM Table1
WHILE EXISTS(SELECT * FROM @HoldTable)
BEGIN
SELECT @Id = id from @HoldTable
EXEC dbo.Sproc @Id
DELETE FROM @HoldTable where Id = @Id
END
editado la segunda respuesta. Estabas seleccionando en @Id en lugar de @HoldTable y tenías una cláusula where de 'where processed = 'N'' pero @HoldTable no tiene dicha columna. La segunda opción ahora debería funcionar. Espero haber entendido tu intención correctamente. – kralco626
Francamente si necesitaba para ejecutar un procedimiento almacenado para un conjunto de datos en lugar si el registro fue escrito para, escribiría el código basado en conjunto en lugar de usar el proceso almacenado. Esta es la única manera eficiente de hacer esto si va a ejecutar contra un conjunto de datos grande. Puede pasar de horas para hacer la inserción que el proceso almacenado hace en segundos o incluso milisegundos. No utilice el procesamiento basado en registros cuando necesite procesar un conjunto de datos, especialmente si no es por una razón tonta, como la reutilización del código. El rendimiento supera la reutilización del código.
Hay algunos elementos en los que absolutamente * debe * utilizar cursores, aunque como en el caso de GOTO, la necesidad real de ellos es realmente muy pequeña. Acuerde que es mejor hacer el procesamiento basado en conjuntos donde sea que tenga sentido, pero su "rendimiento prevalece sobre la reutilización del código" es un poco extremista. –
Como estamos hablando de la diferencia entre minutos y milisegundos u horas y segundos (o minutos), no creo que sea extremista. Los programadores que no consideran el rendimiento de la base de datos sobre la reutilización del código (particularmente cuando se trata de usar cursores) generalmente tienen bases de datos que funcionan muy mal. – HLGEM
Usted fue quien dijo que era segundos vs. horas. En ese caso de hombre de paja, ¿quién podría discutir? Pero si la diferencia es de milisegundos frente a segundos o milisegundos frente al doble de milisegundos, depende. – stannius
De ser posible, escribiría una segunda versión del proceso almacenado que se lee desde una tabla temporal.
Si eso no es posible, probablemente no tenga suerte.
Si solo está usando SQL Server 2005 o posterior, no se preocupa por la compatibilidad con versiones anteriores y puede convertir su código en una Función definida por el usuario (en lugar de un proceso almacenado), puede usar el nuevo " "CROSS APPLY", que usa una sintaxis muy similar a la que desea. He encontrado here una breve introducción (por supuesto, también puede leer los BOLs y MSDN)
Suponiendo que el SP devuelve un solo valor denominado out_int, su ejemplo podría ser reescrita como:
SELECT T.id, UDF.out_int
FROM
Table1 T
CROSS APPLY
dbo.fn_My_UDF(T.id) AS UDF
Este recuperará cada "id" de la Tabla1 y lo usará para llamar a fn_My_UDF, cuyo resultado aparecerá en el conjunto de resultados final además del parámetro original.
Una variante de "APLICACIÓN CRUZADA" es "APLICACIÓN EXTERIOR". Son equivalentes de "INNER JOIN" y "LEFT JOIN", pero trabajan para unirse a una tabla y un UDF (y llamar al segundo al mismo tiempo).
Si usted debe (por orden explícito del jefe con el pelo puntiagudo) utilice los SPs insead, bueno, ¡mala suerte! Tendrá que seguir con los cursores o intentar hacer trampa un poco: cambie el código en UDF y cree SP de envoltura: D.
CROSS APPLY no funciona para los procedimientos almacenados, ya que no devuelven conjuntos de datos, solo informan las salidas. Las funciones devuelven cualquier cosa, por lo que SQL solo puede usarlas cuando se usa CROSS APPLY. Abajo votado. – Fandango68
@ Fernando68 Indiqué 3 condiciones necesarias para usar CROSS APPLY como solución al principio de mi respuesta, la 3ª de las cuales es "puede convertir su código para que sea un UDF en lugar de SP". –
Este bucle funciona, pero fue lento para mi SP.Creo que la respuesta correcta es por HLGEM, su mejor apuesta es escribir una mejor consulta masiva.
DECLARE @id INT
SET @id = 0
DECLARE @max INT
SELECT TOP 1 @max = TableID
FROM dbo.Table
ORDER BY TableID desc
-- loop until BREAK
-- this is how you can perform a DO-WHILE loop in TSQL
WHILE (1 = 1)
BEGIN
SELECT
TOP 1 @id = TableID
FROM dbo.Table
WHERE TableID > @id
IF @id IS NOT NULL
BEGIN
-- call you SP here
PRINT @id
END
-- break out of the loop once the max id has been reached
IF @id = @max BREAK
END
- 1. Ejecutar un procedimiento almacenado dentro de un procedimiento almacenado
- 2. Usar el cursor en un bucle de un procedimiento almacenado
- 3. ¿Cómo desactivo los resultados de la consulta al ejecutar un procedimiento almacenado desde un procedimiento almacenado?
- 4. SQL llamada de procedimiento almacenado para cada fila sin utilizar un cursor
- 5. ¿Cómo ejecutar un procedimiento almacenado de Oracle?
- 6. ¿Es posible utilizar un procedimiento almacenado como subconsulta en SQL Server 2008?
- 7. Servidor SQL: ¿es posible recorrer un procedimiento almacenado?
- 8. Procedimiento almacenado al ejecutar otro procedimiento almacenado
- 9. Cursor dinámico en el procedimiento almacenado
- 10. ¿Cómo selecciono un procedimiento almacenado en Sybase?
- 11. Oracle EJECUTAR INMEDIATO en un cursor
- 12. PL/SQL imprimir ref cursor devuelto por un procedimiento almacenado
- 13. Procedimiento almacenado y permisos: ¿es suficiente EJECUTAR?
- 14. ¿Cómo suprimo los resultados de un procedimiento almacenado dentro de un procedimiento almacenado?
- 15. La instrucción UPDATE utiliza EXEC para ejecutar un procedimiento almacenado para ESTABLECER un valor de columna
- 16. Cómo llamar a un procedimiento almacenado (con parámetros) desde otro procedimiento almacenado sin tabla temporal
- 17. ¿Ejecutar el procedimiento almacenado con un parámetro de salida?
- 18. Cómo llamar a un procedimiento almacenado desde otro procedimiento almacenado?
- 19. ¿Debo usar sp_executesql o EXEC para ejecutar un procedimiento almacenado?
- 20. Cómo guardar un procedimiento almacenado?
- 21. Ejecutar un procedimiento almacenado de SQL y procesar los resultados
- 22. Cómo ejecutar un procedimiento almacenado dentro del programa C#
- 23. ¿Cómo programar un procedimiento almacenado?
- 24. Ejecutar un procedimiento almacenado como permiso de otro usuario
- 25. ¿Usar la función como parámetro al ejecutar un procedimiento almacenado?
- 26. Seleccionar y actualizar en un procedimiento almacenado
- 27. ¿Cómo ejecutar automáticamente un procedimiento almacenado según el programador?
- 28. Cómo llamar a un procedimiento almacenado mediante un cursor ref en Oracle con la ardilla
- 29. Llamar a un procedimiento almacenado en un procedimiento almacenado en MySQL
- 30. ¿Es posible recurrir a un procedimiento almacenado recursivamente en SQL Server?
¿Es esto completamente exacto? ¿Puedes ordenar por ID sin especificar una cláusula group by? –
No funciona bien. No se detiene después de leer la identificación máxima. –
-1 No funciona. Como dijo Richard Collette, la sintaxis seleccionada está rota. Y si arreglas la sintaxis, el tiempo se queda atascado en un ciclo infinito, como señala Tony_Henrich). He agregado una respuesta que tiene un ciclo de trabajo, pero fue lenta en mi experiencia. –