¿Cómo asignar un resultado select a una variable?


¿Cómo puedo almacenar un valor de campo seleccionado en una variable de una consulta y usarlo en una instrucción update?

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 de la tabla de facturas y almacena el Cursor
  2. Obtener id de factura desde cursor - > tmp_key variable
  3. foreach tmp_key encuentra el id de contacto principal del cliente de factura desde la tabla del cliente
  4. actualiza el cliente clave de contacto con id de contacto primario
  5. cerrar 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 puedo almacenar la PrimaryContactKey y volver a usarla en la cláusula set de la siguiente instrucción update? ¿Puedo crear una variable de cursor o simplemente otra variable local con un tipo int?

 67
Author: Tshepang, 2009-04-30

5 answers

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 abogando por el uso del cursor en mi respuesta, sino más bien mostrando cómo asignar el valor basado en la pregunta.

 41
Author: squillman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-18 15:39:24

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
 83
Author: Pawel G.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-24 17:07:05

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 una variable TSQL estándar.

También debo señalar que así es como lo haría para cualquier tipo de select en una variable, no solo cuando se trata de cursores.

 18
Author: TheTXI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-30 16:20:31

¿Por qué necesitas un cursor? Todo su segmento de código puede ser reemplazado por esto, 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'
 13
Author: GilaMonster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-01 19:08:46

Para asignar una variable de forma segura, debe usar 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 tanto un paréntesis inicial como un paréntesis 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 varios posts

¿Qué sucede si la siguiente selección resulta 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 del último post en el resultado.

De hecho, a @PrimaryContactKey se le asignará un valor por mensaje en el resultado, por lo que contendrá el valor del último mensaje que el comando SELECT estaba procesando.

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

Con a SET-SELECT sentencia su variable se establecerá en null.

2. El SELECT devuelve no posts

¿Qué sucede, cuando se utiliza la segunda versión del código, si su selección no devuelve un resultado en absoluto?

En un contrario a lo que usted puede creer el valor de la variable no será nulo - se mantendrá es el valor anterior!

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

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

Ver también: ¿ESTABLECER versus SELECCIONAR al asignar variables?

 9
Author: Erk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:15