Comment enregistrer une valeur de champ sélectionnée dans une variable à partir d'une requête et l'utiliser dans une instruction de mise à jour?
Voici ma procédure:
J'écris une procédure stockée SQL Server 2005 T-SQL qui effectue les opérations suivantes:
Voici mon code:
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
Comment puis-je stocker la PrimaryContactKey et l'utiliser à nouveau dans la clause set de la déclaration de mise à jour suivante? Est-ce que je crée une variable de curseur ou juste une autre variable locale avec un type int?
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
EDIT:
Cette question a eu beaucoup plus de succès que je ne l'aurais cru. Notez que je ne préconise pas l'utilisation du curseur dans ma réponse, mais montre plutôt comment attribuer la valeur en fonction de la question.
Je viens d'avoir le même problème et ...
declare @userId uniqueidentifier
set @userId = (select top 1 UserId from aspnet_Users)
ou même plus court:
declare @userId uniqueidentifier
SELECT TOP 1 @userId = UserId FROM aspnet_Users
Essaye ça
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
Vous déclareriez cette variable en dehors de votre boucle en tant que variable TSQL standard.
Je devrais également noter que c'est comme cela que vous feriez pour n'importe quel type de sélection dans une variable, pas seulement lorsqu'il s'agit de curseurs.
Pourquoi avez-vous besoin d'un curseur? Tout votre segment de code peut être remplacé par ceci, ce qui fonctionnera beaucoup plus rapidement sur un grand nombre de lignes.
UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey
FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey
WHERE confirmtocntctkey is null and tranno like '%115876'
Pour affecter une variable en toute sécurité, vous devez utiliser l'instruction SET-SELECT:
SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey
AND i.invckey = @tmp_key)
Assurez-vous d'avoir une parenthèse de début et de fin!
La raison pour laquelle la version de SET-SELECT est le moyen le plus sûr de définir une variable est double.
1. Le SELECT retourne plusieurs posts
Que se passe-t-il si les résultats de sélection suivants apparaissent dans plusieurs messages?
SELECT @PrimaryContactKey = c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey
AND i.invckey = @tmp_key
@PrimaryContactKey
se verra attribuer la valeur du dernier message dans le résultat.
En réalité @PrimaryContactKey
se verra attribuer une valeur par publication dans le résultat et contiendra donc la valeur de la dernière publication traitée par la commande SELECT.
La dernière publication est déterminée par les index clusterisés ou, si aucun index clusterisé n'est utilisé ou si la clé primaire n'est clusterisée, la "dernière" publication sera la dernière publication ajoutée. Dans le pire des cas, ce comportement pourrait être modifié chaque fois que l'indexation de la table est modifiée.
Avec une instruction SET-SELECT, votre variable sera définie sur null
.
2. Le SELECT ne renvoie aucun message
Que se passe-t-il, lorsque vous utilisez la deuxième version du code, si votre sélection ne renvoie aucun résultat?
Contrairement à ce que vous pouvez croire, la valeur de la variable ne sera pas nulle - elle conservera sa valeur précédente !
En effet, comme indiqué ci-dessus, SQL affectera une valeur à la variable une fois par publication - ce qui signifie que la variable ne fera rien si le résultat ne contient aucune publication. Ainsi, la variable aura toujours la valeur qu'elle avait avant l'exécution de l'instruction.
Avec l'instruction SET-SELECT, la valeur sera null
.
Voir aussi: SET versus SELECT lors de l'affectation de variables?