Delen via


Gepositioneerde update- en delete-instructies simuleren

Als de gegevensbron geen geplaaste update- en verwijderinstructies ondersteunt, kan het stuurprogramma deze simuleren. De ODBC-cursorbibliotheek simuleert bijvoorbeeld gepositioneerde update- en delete-instructies. De algemene strategie voor het simuleren van gepositioneerde update- en verwijderinstructies is het converteren van gepositioneerde instructies naar gezochte statements. Dit wordt gedaan door de WHERE CURRENT OF-component te vervangen door een doorzochte WHERE-component die de huidige rij identificeert.

Omdat de kolom CustID bijvoorbeeld elke rij in de tabel Klanten uniek identificeert, wordt de positie van de verwijderingsinstructie

DELETE FROM Customers WHERE CURRENT OF CustCursor  

kan worden geconverteerd naar

DELETE FROM Customers WHERE (CustID = ?)  

Het stuurprogramma kan een van de volgende rij-id's in de WHERE-clausule gebruiken:

  • Kolommen waarvan de waarden dienen om elke rij in de tabel uniek te identificeren. Als u bijvoorbeeld SQLSpecialColumns aanroept met SQL_BEST_ROWID, wordt de optimale kolom of set kolommen geretourneerd die voor dit doel dienen.

  • Pseudokolommen, geleverd door sommige gegevensbronnen, om elke rij uniek te identificeren. Deze kunnen ook worden opgehaald door SQLSpecialColumns aan te roepen.

  • Een unieke index, indien beschikbaar.

  • Alle kolommen in de resultaatset.

Welke kolommen een stuurprogramma moet gebruiken in de WHERE-component die het maakt, is afhankelijk van het stuurprogramma. In sommige gegevensbronnen kan het bepalen van een rij-id kostbaar zijn. Het uitvoeren ervan gaat echter sneller en garandeert dat een gesimuleerde opdracht of statement hoogstens één rij bijwerkt of verwijdert. Afhankelijk van de mogelijkheden van het onderliggende databasebeheersysteem kan het instellen van een rij-identificator duur zijn. Het is echter sneller om uit te voeren en garandeert dat een gesimuleerde instructie slechts één rij bijwerkt of verwijdert. De optie voor het gebruik van alle kolommen in de resultatenset is meestal veel eenvoudiger in te stellen. Het is echter langzamer om uit te voeren en als de kolommen een rij niet uniek identificeren, kan dit ertoe leiden dat rijen onbedoeld worden bijgewerkt of verwijderd, met name wanneer de selectielijst voor de resultatenset niet alle kolommen bevat die in de onderliggende tabel aanwezig zijn.

Afhankelijk van welke van de voorgaande strategieën het stuurprogramma ondersteunt, kan een toepassing kiezen welke strategie door het stuurprogramma wordt gebruikt met de instructie-eigenschap SQL_ATTR_SIMULATE_CURSOR. Hoewel het misschien vreemd lijkt voor een toepassing om onbedoeld een rij bij te werken of te verwijderen, kan de toepassing dit risico verwijderen door ervoor te zorgen dat de kolommen in de resultatenset elke rij in de resultatenset uniek identificeren. Dit bespaart de bestuurder de moeite om dit te doen.

Als de driver ervoor kiest om een rij-id te gebruiken, wordt de SELECT FOR UPDATE-instructie onderschept waarmee de resultatenset wordt gemaakt. Als de kolommen in de selectielijst een rij niet effectief identificeren, voegt het stuurprogramma de benodigde kolommen toe aan het einde van de selectielijst. Sommige gegevensbronnen hebben één kolom die altijd een rij identificeert, zoals de kolom ROWID in Oracle; als een dergelijke kolom beschikbaar is, gebruikt het stuurprogramma dit. Anders roept het stuurprogramma SQLSpecialColumns aan voor elke tabel in de FROM-component om een lijst op te halen met de kolommen die elke rij uniek identificeren. Een veelvoorkomende beperking die het gevolg is van deze techniek, is dat cursorsimulatie mislukt als er meer dan één tabel in de FROM-component staat.

Ongeacht hoe het stuurprogramma rijen identificeert, wordt meestal de FOR UPDATE OF van de SELECT FOR UPDATE-instructie verwijderd voordat deze naar de gegevensbron wordt verzonden. De FOR UPDATE OF clausule wordt alleen gebruikt met positioned update- en delete-instructies. Gegevensbronnen die geen ondersteuning bieden voor positioned update- en delete-instructies, bieden doorgaans geen ondersteuning voor deze instructies.

Wanneer de toepassing een gepositioneerde update- of verwijderinstructie verzendt voor uitvoering, vervangt het stuurprogramma de WHERE CURRENT OF-clausule door een WHERE-clausule die de rij-id bevat. De waarden van deze kolommen worden opgehaald uit een cache die wordt onderhouden door het stuurprogramma voor elke kolom die in de WHERE-component wordt gebruikt. Nadat het stuurprogramma de WHERE-component heeft vervangen, wordt de instructie verzonden naar de gegevensbron voor uitvoering.

Stel dat de toepassing de volgende instructie indient om een resultatenset te maken:

SELECT Name, Address, Phone FROM Customers FOR UPDATE OF Phone, Address  

Als de toepassing SQL_ATTR_SIMULATE_CURSOR heeft ingesteld om een garantie van uniekheid aan te vragen en de gegevensbron geen pseudokolom biedt die altijd een rij uniek identificeert, dan roept het stuurprogramma SQLSpecialColumns aan voor de tabel Klanten. Het ontdekt dat CustID de sleutel is voor de tabel Klanten, voegt dit element toe aan de selectielijst en verwijdert de FOR UPDATE OF-component.

SELECT Name, Address, Phone, CustID FROM Customers  

Als de toepassing geen uniekheidsgarantie heeft aangevraagd, wordt alleen de FOR UPDATE OF-clausule verwijderd door de driver.

SELECT Name, Address, Phone FROM Customers  

Stel dat de toepassing door de resultatenset bladert en de volgende geplaatste update-instructie verzendt voor uitvoering, waarbij Cust de naam is van de cursor boven de resultatenset:

UPDATE Customers SET Address = ?, Phone = ? WHERE CURRENT OF Cust  

Als de toepassing geen garantie voor uniekheid heeft aangevraagd, vervangt het stuurprogramma de WHERE-component en verbindt de CustID-parameter met de variabele in de cache:

UPDATE Customers SET Address = ?, Phone = ? WHERE (CustID = ?)  

Als de toepassing geen garantie voor uniekheid heeft aangevraagd, vervangt het stuurprogramma de WHERE-component en verbindt de parameters Name, Address en Phone in deze component met de variabelen in de cache:

UPDATE Customers SET Address = ?, Phone = ?  
   WHERE (Name = ?) AND (Address = ?) AND (Phone = ?)