2010-11-04 3 views
0

Dans Sql Server 2008 r2, j'ai une table appelée Emp, et j'essaye de mettre à jour certaines valeurs dans une transaction (tran externe), maintenant après la mise à jour et avant le commit, j'ai commencé une autre transaction, dans laquelle j'ai essayé de sélectionner les données de la même table (Emp) mais via un serveur lié loopback. le look tsql comme ceci:une instruction select dans une transaction contre un serveur lié loopback ne s'arrête jamais

USE MASTER 

GO 

EXEC sp_addlinkedserver @server = N'loopback',@srvproduct=N'',@provider = N'SQLNCLI', @datasrc = @@SERVERNAME,@catalog = 'MstrDtl' 
GO 

EXEC sp_serveroption loopback,N'remote proc transaction promotion','FALSE' 

Go 

create SYNONYM loopy FOR loopback.MstrDtl.dbo.Emp 


use MstrDtl 
BEGIN TRAN OuterTran 
     BEGIN 
     update table dbo.Emp set Salary = 123456 where Name='abcdx' 
      BEGIN TRAN InnerTran 
        select Salary from loopy where Name = 'abcdx' 
      COMMIT TRAN InnerTran 
      ROLLBACK TRAN OuterTran 
     END 

j'ai donc deux questions:

  • peut-je obtenir des anciennes valeurs (les lignes affectées à la mise à jour) dans la requête pour loopback à l'intérieur du InnerTran en utilisant cette façon ?
  • la requête ne s'arrête jamais, aucune idée?

Répondre

0

Pour répondre à vos questions:

  1. Non, vous ne pouvez pas obtenir les anciennes valeurs de cette façon; vous serez bloqué (voir # 2) ou vous obtiendrez les nouvelles valeurs. La raison pour laquelle la requête ne s'arrête jamais est parce que vous vous bloquez (techniquement, vous vous imposez vous-même.) Votre transaction externe maintient un verrou sur cette ligne (page en fait) et la requête de bouclage est bloquée jusqu'à ce que le verrou de mise à jour est libéré. Vous pouvez (mais ne doit pas) spécifier WITH (NOLOCK) sur votre requête de bouclage mais cela retournera réellement la ligne mise à jour mais non engagée.

Si vous voulez les valeurs OLD dans votre requête, utilisez la clause OUTPUT. http://msdn.microsoft.com/en-us/library/ms177564.aspx

CREATE TABLE #emp 
(
    id INT IDENTITY PRIMARY KEY CLUSTERED, 
    empName VARCHAR(255), 
    salary MONEY 
) 
go 

INSERT INTO #emp(empName, salary) 
SELECT 'bill', 5000 
UNION ALL 
SELECT 'ted', 5000 
UNION ALL 
SELECT 'cheech', 35000 
UNION ALL 
SELECT 'chong', 15000 
UNION ALL 
SELECT 'tango', 70000 
UNION ALL 
SELECT 'Cash', 200000 

GO 

DECLARE @oldValues TABLE 
(
    id INT, 
    empname VARCHAR(255), 
    salary money 
) 


UPDATE #emp SET salary = salary + 500 
OUTPUT DELETED.* INTO @oldValues 
WHERE empName = 'bill' 

SELECT E.empName, E.salary AS NewSalary, O.salary AS OldSalary 
FROM #emp E 
    INNER JOIN @oldValues O 
     ON E.id = O.id 

DROP TABLE #emp 
Questions connexes