¿Cómo se puede llamar a un procedimiento almacenado para cada fila en una tabla, donde las columnas de una fila son parámetros de entrada al sp sin usar un cursor?
sql
sql-server
stored-procedures
cursor
Johannes Rudolph
fuente
fuente
Respuestas:
En términos generales, siempre busco un enfoque basado en conjuntos (a veces a expensas de cambiar el esquema).
Sin embargo, este fragmento tiene su lugar ...
fuente
Podría hacer algo como esto: ordene su tabla, por ejemplo, CustomerID (usando la
Sales.Customer
tabla de ejemplo AdventureWorks ) e itere sobre esos clientes usando un ciclo WHILE:Eso debería funcionar con cualquier tabla siempre que pueda definir algún tipo de
ORDER BY
en una columna.fuente
Ok, entonces nunca pondría ese código en producción, pero sí satisface tus requisitos.
fuente
La respuesta de Marc es buena (¡lo comentaría si pudiera resolver cómo hacerlo!)
Solo pensé en señalar que puede ser mejor cambiar el ciclo para que
SELECT
solo exista una vez (en un caso real donde necesito hacer esto,SELECT
era bastante complejo, y escribirlo dos veces era un problema de mantenimiento arriesgado).fuente
Si puede convertir el procedimiento almacenado en una función que devuelve una tabla, puede usar la aplicación cruzada.
Por ejemplo, supongamos que tiene una tabla de clientes y desea calcular la suma de sus pedidos, crearía una función que tomara un CustomerID y devolviera la suma.
Y podrías hacer esto:
Donde se vería la función:
Obviamente, el ejemplo anterior podría hacerse sin una función definida por el usuario en una sola consulta.
El inconveniente es que las funciones son muy limitadas: muchas de las características de un procedimiento almacenado no están disponibles en una función definida por el usuario, y la conversión de un procedimiento almacenado en una función no siempre funciona.
fuente
Usaría la respuesta aceptada, pero otra posibilidad es usar una variable de tabla para contener un conjunto de valores numerados (en este caso, solo el campo ID de una tabla) y recorrerlos por Número de fila con un JOIN a la tabla para recupere lo que necesite para la acción dentro del bucle.
fuente
Para SQL Server 2005 en adelante, puede hacer esto con CROSS APPLY y una función con valores de tabla.
Solo por claridad, me refiero a aquellos casos en los que el procedimiento almacenado se puede convertir en una función con valores de tabla.
fuente
Esta es una variación de la solución n3rds anterior. No se necesita ordenar usando ORDER BY, ya que se usa MIN ().
Recuerde que CustomerID (o cualquier otra columna numérica que use para el progreso) debe tener una restricción única. Además, para hacerlo lo más rápido posible se debe indexar CustomerID.
Utilizo este enfoque en algunos varchars que necesito revisar, colocándolos primero en una tabla temporal, para darles una identificación.
fuente
Si no sabe qué usar un cursor, creo que tendrá que hacerlo externamente (obtenga la tabla y luego ejecute para cada instrucción y cada vez que llame al sp) Es lo mismo que usar un cursor, pero solo afuera SQL ¿Por qué no usarás un cursor?
fuente
Esta es una variación de las respuestas ya proporcionadas, pero debería funcionar mejor porque no requiere ORDER BY, COUNT o MIN / MAX. La única desventaja con este enfoque es que debe crear una tabla temporal para contener todos los ID (se supone que tiene vacíos en su lista de ID de cliente).
Dicho esto, estoy de acuerdo con @Mark Powell, aunque, en términos generales, un enfoque basado en conjuntos aún debería ser mejor.
fuente
Por lo general, lo hago de esta manera cuando hay bastantes filas:
(Sin embargo, en conjuntos de datos más grandes, usaría una de las soluciones mencionadas anteriormente).
fuente
DELIMITADOR //
fuente
Una mejor solución para esto es
Este fue un resultado limpio con formato de tabla. Mientras que si ejecuta SP para cada fila, obtiene un resultado de consulta separado para cada iteración que es feo.
fuente
En caso de que el orden sea importante
fuente
Tenía un código de producción que solo podía manejar a 20 empleados a la vez, a continuación se muestra el marco para el código. Acabo de copiar el código de producción y eliminé las cosas a continuación.
fuente
Me gusta hacer algo similar a esto (aunque todavía es muy similar a usar un cursor)
[código]
[/código]
Tenga en cuenta que no necesita la identidad o la columna isIterated en su tabla temporal / variable, solo prefiero hacerlo de esta manera para no tener que eliminar el registro superior de la colección mientras itero a través del ciclo.
fuente