Pregunta

¿Cómo almaceno un valor de campo seleccionado en una variable de una consulta y lo uso en una declaración de actualización?

Aquí está mi procedimiento:

Estoy escribiendo un procedimiento almacenado de SQL Server 2005 T-SQL que hace lo siguiente:

  1. obtiene la lista de ID de facturas desde la tabla de facturas y las tiendas hasta el cursor
  2. Recupere el ID de la factura desde el cursor - > variable tmp_key
  3. foreach tmp_key encuentra el ID de contacto primario del cliente de la factura en la tabla de clientes
  4. actualiza la clave de contacto del cliente con el ID de contacto principal
  5. cierre el cursor

Aquí está mi código:

DECLARE @tmp_key int
DECLARE @get_invckey cursor 

set @get_invckey = CURSOR FOR 
    select invckey from tarinvoice where confirmtocntctkey is null and tranno like '%115876'

OPEN @get_invckey 

FETCH NEXT FROM @get_invckey into @tmp_key

WHILE (@@FETCH_STATUS = 0) 
BEGIN 
    SELECT c.PrimaryCntctKey as PrimaryContactKey
    from tarcustomer c, tarinvoice i
    where i.custkey = c.custkey and i.invckey = @tmp_key

    UPDATE tarinvoice set confirmtocntctkey = PrimaryContactKey where invckey = @tmp_key
    FETCH NEXT FROM @get_invckey INTO @tmp_key
END 

CLOSE @get_invckey
DEALLOCATE @get_invckey

¿Cómo almaceno la PrimaryContactKey y la uso nuevamente en la cláusula set de la siguiente declaración de actualización? ¿Creo una variable de cursor o simplemente otra variable local con un tipo int?

¿Fue útil?

Solución

DECLARE @tmp_key int
DECLARE @get_invckey cursor 

SET @get_invckey = CURSOR FOR 
    SELECT invckey FROM tarinvoice WHERE confirmtocntctkey IS NULL AND tranno LIKE '%115876'

OPEN @get_invckey 

FETCH NEXT FROM @get_invckey INTO @tmp_key

DECLARE @PrimaryContactKey int --or whatever datatype it is

WHILE (@@FETCH_STATUS = 0) 
BEGIN 
    SELECT @PrimaryContactKey=c.PrimaryCntctKey
    FROM tarcustomer c, tarinvoice i
    WHERE i.custkey = c.custkey AND i.invckey = @tmp_key

    UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key
    FETCH NEXT FROM @get_invckey INTO @tmp_key
END 

CLOSE @get_invckey
DEALLOCATE @get_invckey

EDITAR:
Esta pregunta ha recibido mucha más tracción de la que hubiera previsto. Tenga en cuenta que no estoy recomendando el uso del cursor en mi respuesta, sino que muestro cómo asignar el valor en función de la pregunta.

Otros consejos

Acabo de tener el mismo problema y ...

declare @userId uniqueidentifier
set @userId = (select top 1 UserId from aspnet_Users)

o incluso más corto:

declare @userId uniqueidentifier
SELECT TOP 1 @userId = UserId FROM aspnet_Users

Prueba esto

SELECT @PrimaryContactKey = c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key

UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey 
WHERE invckey = @tmp_key
FETCH NEXT FROM @get_invckey INTO @tmp_key

Usted declararía esta variable fuera de su bucle como solo una variable TSQL estándar.

También debo tener en cuenta que esta es la forma en que lo haría para cualquier tipo de selección en una variable, no solo cuando se trata de cursores.

¿Por qué necesitas un cursor? Todo este segmento de código puede ser reemplazado por este, que se ejecutará mucho más rápido en un gran número de filas.

UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey 
FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey
WHERE confirmtocntctkey is null and tranno like '%115876'

Para asignar una variable de forma segura, debe utilizar la instrucción SET-SELECT:

SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey
    FROM tarcustomer c, tarinvoice i
    WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key)

¡Asegúrate de tener un paréntesis inicial y otro final!

La razón por la que la versión SET-SELECT es la forma más segura de establecer una variable es doble.

1. El SELECT devuelve varias publicaciones

¿Qué sucede si lo siguiente selecciona resultados en varias publicaciones?

SELECT @PrimaryContactKey = c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key

@PrimaryContactKey se le asignará el valor de la última publicación en el resultado.

De hecho, a @PrimaryContactKey se le asignará un valor por publicación en el resultado, por lo tanto, contendrá el valor de la última publicación que el comando SELECT estaba procesando.

¿Qué publicación es " última " está determinado por cualquier índice agrupado o, si no se utiliza ningún índice agrupado o si la clave primaria está agrupada, la " última " La publicación será la publicación más reciente. Este comportamiento podría, en el peor de los casos, modificarse cada vez que se cambie la indexación de la tabla.

Con una instrucción SET-SELECT, su variable se establecerá en null .

2. SELECT no devuelve ninguna publicación

¿Qué sucede cuando se usa la segunda versión del código, si su selección no devuelve ningún resultado?

Al contrario de lo que pueda creer, el valor de la variable no será nulo . ¡Retendrá su valor anterior!

Esto se debe a que, como se indicó anteriormente, SQL asignará un valor a la variable una vez por publicación , lo que significa que no hará nada con la variable si el resultado no contiene publicaciones. Por lo tanto, la variable seguirá teniendo el valor que tenía antes de ejecutar la declaración.

Con la instrucción SET-SELECT, el valor será null .

Consulte también: SET versus SELECT al asignar variables?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top