2010-12-06 23 views
2

SQL Server 2008: J'ai ici une situation dans laquelle je souhaite lire dans une table et écrire une ligne dans certaines conditions. Le problème est que je ne veux pas qu'une autre demande arrive exactement au même moment et fasse la même chose. Je vais essayer d'expliquer ici:SQL Query Exclusif Lecture/écriture au tableau

Nom de la table: RequestQueue

Columns: 

RequestID, StartDate, EndDate, RequestResult 

Sample Data 

1, 12/4/10 1:00pm, 12/4/10 1:02pm, Success 
2, 12/4/10 1:04pm, 12/4/10 1:05pm, Success 
3, 12/4/10 1:00pm, NULL, NULL 

Lorsqu'une page se charge dans mon application, je le veux à regarder ce tableau et s'il y a une demande toujours en attente comme (ID # 3) il ne fera rien. Sinon, s'il n'y a aucune demande en attente, elle crée une nouvelle ligne avec l'ID et StartDate remplis.

Le problème est que nous pouvons nous retrouver dans une situation où la page est chargée deux fois presque exactement au même moment. S'il arrive que les deux lisent de la table avant que la nouvelle ligne ne soit produite, alors je pourrais avoir deux nouvelles lignes là-dedans. Je veux avoir une sorte de requête qui lit à partir de la table et s'il n'y a aucune demande en attente, insère la nouvelle ligne avec le StartDate rempli. Je veux que cette requête s'exécute complètement avant qu'une autre page puisse même lire de cette table Je ne reçois pas l'effet "double rangée".

je pourrais avoir besoin « verrouillage » ou quelque chose, je googlé cela, mais n'ont pas trouvé quelque chose pour ma situation exacte. Je suis sûr que cela pourrait être une procédure stockée simple J'ai juste besoin d'une poussée dans la bonne direction ici.

Merci,

Robert

+1

Que SGBDR utilisez-vous? MySQL, SQL Server, etc? – JNK

+1

Quels SGBDR et version? Voulez-vous également bloquer ** toutes ** les lectures simultanées de la table ou y a-t-il des lectures qui ne sont pas liées au processus d'insertion qui serait mieux autorisé? –

+2

Oh désolé, SQL Server 2008 – Robert

Répondre

2

En supposant que vous voulez juste bloquer tous les accès simultané à la table, vous pouvez simplement faire.

BEGIN TRAN 

DECLARE @StartDate datetime, 
     @EndDate datetime 

SELECT TOP 1 
      @StartDate = StartDate, 
      @EndDate = EndDate 
     FROM  RequestQueue WITH(TABLOCK,XLOCK) 
     ORDER BY RequestID DESC 


IF @EndDate IS NULL 
    SELECT @StartDate AS 'StartDate' 
ELSE 
    INSERT INTO RequestQueue (StartDate) 
    OUTPUT INSERTED.* /* Or use SCOPE_IDENTITY() instead*/ 
    VALUES (GETDATE()) 

COMMIT 

Sinon, vous pouvez simplement serialise accès au code SELECT/INSERT dans la procédure spécifique sans prendre un verrou de table exclusif en utilisant sp_getapplock

+0

OK, ceci est proche. Donc sur le "si non existant" je dois seulement vérifier la dernière rangée avec EndDate = NULL. (Il pourrait y avoir d'autres lignes dans l'historique qui ne se sont jamais terminées avec et EndDate) En outre, après l'insertion, puis-je sélectionner de nouveau le nouvel ID pour cette rangée? Enfin, comment est-ce que je le fais retourner le StartDate de la dernière rangée dans le cas où la rangée est réellement inachevée? Merci – Robert

+0

Voir la mise à jour de la réponse. –

+0

Bon Martin, merci! J'apprécie vraiment cela. – Robert