2010-12-06 3 views
2

Eh bien, j'essaie d'écrire un déclencheur où un client essaie d'acheter quelque chose, mais s'il passe sa limite de cartes de crédit, la transaction doit être annulé.MSSQL Trigger: L'identifiant multi-parties "i.charged_amount" ne peut pas être lié

mes tables sont:
clients (nom, numéro de sécurité sociale, Code),
comptes (customer_code, acc_number, équilibre, taux),
creditcard (émis, expiré, limite, l'équilibre, cc_number),
transactions (date, cc_number, charged_amount, ** conf_numb ** er, shop_code)

et ce que je l'ai écrit est

create trigger check_balance on transactions 
for insert 
as 
Declare @balance int, 
     @limit int 
SELECT @balance = balance, @limit = limit 
FROM creditcard INNER JOIN inserted i ON creditcard.cc_number = i.cc_number 

IF (@balance + i.charged_amount > @limit) 
BEGIN 

    ROLLBACK TRANSACTION 
END 

Mais je reçois un

Msg 4104, Niveau 16, État 1, Procédure check_balance, ligne 10 L'identifiant multi-partie "i.charged_amount" ne pouvait pas être lié. où ligne 10 est IF (@balance + i.charged_amount> @limit) Je sais que le masg signifie que je ne peux pas utiliser i. *, Parce que la portée de celui-ci est seulement dans le select..from. J'ai essayé d'utiliser la nouvelle ligne de référencement comme je, mais j'ai eu une erreur de syntaxe près de référencement. J'utilise le serveur MSSQL 2005 je ne suis pas trop familier avec les déclencheurs dans sql, alors pourriez-vous s'il vous plaît m'aider?

Répondre

3

essayez ceci:

create trigger check_balance on transactions 

for insert 
as 

IF EXISTS (SELECT 1 
      FROM creditcard 
       INNER JOIN inserted i ON creditcard.cc_number = i.cc_number 
      GROUP BY c.cc_number 
      HAVING MIN(creditcard.balance)+SUM(i.charged_amount)>MIN(creditcard.limit) 
     ) 
BEGIN 
    raiserror ('bad limit found',16,1) 
    ROLLBACK TRANSACTION 
    return 
END 
+0

Cela permettrait toujours à travers plusieurs achats différents sur la même carte qui dépassent collectivement la limite de compte. –

+0

@Martin, bonne prise, vous obtenez un "A" sur les devoirs pour aujourd'hui! –

+0

Ha Ha! +1 Pour le correctif –

5

Votre affectation à des variables scalaires ne fonctionnera pas avec des inserts en ligne multi. inserted est une table qui peut contenir n'importe quel nombre de lignes.

Un insert peut même contenir plusieurs lignes différentes pour la même carte de crédit qui, individuellement, sont correctes mais qui, collectivement, dépasseraient la limite de compte.

La logique devrait être quelque chose comme ...

IF EXISTS 
(
SELECT c.cc_number 
FROM creditcard c 
INNER JOIN inserted i ON c.cc_number = i.cc_number 
GROUP BY c.cc_number, c.limit, c.balance 
HAVING c.balance + SUM(i.charged_amount) > c.limit 
) 

ROLLBACK... 
+0

+1, bonne prise avec le problème des transactions multiples! vous pouvez exécuter une petite transaction 1000 fois pour obtenir la limite sans cette vérification: '; WITH AllNumbers AS (SELECT 1 AS Numéro UNION ALL SELECT Numéro + 1 FROM AllNumbers WHERE Nombre <1000) INSERT INTO transactions (date, cc_number, loaded_amount, conf_number, shop_code) SELECT GETDATE(), '12345', 100,1234, 'X' FROM ALLNumbers OPTION (MAXRECURSION 1000) ' –

-4

Je pense que le problème est que vous essayez d'utiliser l'alias i quand il est seulement dans la portée de la requête que vous Aliased dans. Veuillez changer la référence dans l'instruction IF à insérée au lieu de i.

+1

Besoin de beaucoup plus que cela, désolé – gbn

+0

Et en changeant IF (@balance + i.charged_amount> @ limite) à IF (@balance + inserted.charged_amount> @limit) est faux comment? Je ne suis pas sûr pourquoi j'ai été downvoted. –

Questions connexes