Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Beide drivers kunnen één instructie uitvoeren of een instructie voorbereiden voor herhaalde uitvoering. Gebruik parameters voor waarden die door gebruikers worden opgegeven, zelfs als je maar één query uitvoert.
Kies de uitvoerings-API apart van hoe je de resultaten ophaalt. Het voorbereiden van een query haalt de rijen niet op, en het bufferen van een resultaat maakt een query niet geparametriseerd. De volgende voorbeelden bereiden één keer een alleen-lezen query voor, voeren deze twee keer uit met verschillende waarden en consumeren elk resultaat vóór de volgende uitvoering.
| Uitvoeringsstijl | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Voer één keer een query uit, zonder parameters | sqlsrv_query | PDO::query voor resultaten, of PDO::exec voor getroffen-rijtellingen |
| Voer één keer een query uit, met parameters | sqlsrv_query($conn, $sql, $params) |
PDO::prepare() gevolgd door PDOStatement::execute() |
| Bereid één keer voor, voer herhaaldelijk uit met verschillende parameters | sqlsrv_prepare + sqlsrv_execute | PDO::prepare + PDOStatement::execute |
sqlsrv_query() bereidt voor en voert uit in één aanroep en retourneert een statementresource.
sqlsrv_prepare() geeft een statementresource terug zonder deze uit te voeren; roep sqlsrv_execute() voor elke uitvoering aan. PDO's query() voert uit en retourneert PDOStatement, terwijl exec() het aantal getroffen rijen retourneert in plaats van een resultaatobject. Een succesvolle exec() kan teruggeven 0, dus vergelijk een mislukte return met === false, niet if (!$count).
PDO::query() accepteert geen array van parameterwaarden. De optionele argumenten ervan configureren het ophalen. Voor geparametriseerde PDO_SQLSRV queries gebruik prepare() en execute().
Eerst voorbereiden stelt je in staat een statementhandle met andere waarden opnieuw te gebruiken. Dit is geen garantie dat de server zijn uitvoeringsplan nooit opnieuw compileert. PDO_SQLSRV gebruikt standaard prepared execution, inclusief voor PDO::query(); zijn directquery-attribuut beheert die aparte keuze.
Bereid één keer voor en voer het herhaaldelijk uit
Dit zijn aparte, volledige commandoregelprogramma's. Installeer en laad de geselecteerde extensie, en stel SQL_DATABASE, SQL_USER, SQL_PASSWORD en SQL_SERVER in de PHP-procesomgeving in. Gebruik een SQL Server testdatabase en een servercertificaat dat door de client wordt vertrouwd. Voor de omgevingsinstallatie en wachtwoordloze alternatieven, zie Verbinden met de server.
Sla de daadwerkelijke databasenaam, gebruikersnaam en wachtwoord op in de omgevingsvariabelen. Beide programma's escapen deze waarden één keer door sluitende accolades te verdubbelen en elke waarde tussen accolades te plaatsen, zoals vereist door de ODBC-achtige verbindingsafhandeling van de PHP-driver. Het ontsnappen van verbindingswaarden staat los van het binden van queryparameters.
De programma's voeren een Transact-SQL (T-SQL) query uit over twee inline rijen zonder een tabel aan te maken of data te wijzigen. Sla elk programma op in een eigen .php bestand en voer het uit met php <file>. Er is geen voorbeelddatabase vereist.
SQLSRV
Geef $productId via referentie door met &$productId. Elke sqlsrv_execute() gebruikt vervolgens zijn huidige waarde.
SQLSRV_FETCH_ASSOC geeft een array terug die is gesleuteld op kolomnaam. Een false resultaat betekent dat er geen rijen meer zijn; null duidt op een fout.
<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$value = getenv($name);
if ($value === false || $value === '') {
throw new RuntimeException("Set $name before running this example.");
}
$config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$conn = sqlsrv_connect($config['SQL_SERVER'], [
'Database' => $config['SQL_DATABASE'],
'UID' => $config['SQL_USER'],
'PWD' => $config['SQL_PASSWORD'],
'Encrypt' => true,
'TrustServerCertificate' => false,
'LoginTimeout' => 30,
'CharacterSet' => 'UTF-8',
]);
if ($conn === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$sql = "SELECT Name FROM (VALUES (1, 'Bike'), (2, 'Helmet')) AS Product(ProductId, Name) WHERE ProductId = ?";
$productId = 1;
$stmt = null;
try {
$stmt = sqlsrv_prepare($conn, $sql, [&$productId], ['QueryTimeout' => 30]);
if ($stmt === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
foreach ([1 => 'Bike', 2 => 'Helmet'] as $productId => $expected) {
if (!sqlsrv_execute($stmt)) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$names = [];
while (($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) !== null) {
if ($row === false) {
throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$names[] = $row['Name'];
}
if ($names !== [$expected]) {
throw new RuntimeException('Expected exactly one matching product.');
}
echo $names[0], PHP_EOL;
}
} finally {
if (is_resource($stmt)) {
sqlsrv_free_stmt($stmt);
}
sqlsrv_close($conn);
}
PDO_SQLSRV
Bind $productId één keer met bindParam(). Elke execute() kaart leest zijn huidige waarde af.
PDO::PARAM_INT specificeert het PHP/PDO-bindingstype van de parameter; het bepaalt niet het PHP-type van kolommen dat uit het resultaat wordt gehaald. Stel uitzonderingsmodus in zodat een databasefout de uitvoering onderbreekt in plaats van te verwarren met een leeg resultaat.
<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$value = getenv($name);
if ($value === false || $value === '') {
throw new RuntimeException("Set $name before running this example.");
}
$config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
$config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$server = $config['SQL_SERVER'];
$database = $config['SQL_DATABASE'];
$pdo = new PDO(
"sqlsrv:Server=$server;Database=$database;Encrypt=true;"
. "TrustServerCertificate=false;LoginTimeout=30",
$config['SQL_USER'],
$config['SQL_PASSWORD'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8,
]
);
$sql = "SELECT Name FROM (VALUES (1, 'Bike'), (2, 'Helmet')) AS Product(ProductId, Name) WHERE ProductId = ?";
$stmt = null;
try {
$stmt = $pdo->prepare($sql, [PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30]);
$productId = 1;
$stmt->bindParam(1, $productId, PDO::PARAM_INT);
foreach ([1 => 'Bike', 2 => 'Helmet'] as $productId => $expected) {
$stmt->execute();
$names = $stmt->fetchAll(PDO::FETCH_COLUMN);
if ($names !== [$expected]) {
throw new RuntimeException('Expected exactly one matching product.');
}
echo $names[0], PHP_EOL;
$stmt->closeCursor();
}
} finally {
$stmt = null;
$pdo = null;
}
Elk voorbeeld drukt af:
Bike
Helmet
Waarden in een array die aan PDO's wordt doorgegeven, execute() worden behandeld als PDO::PARAM_STR. Wanneer SQL een geheel getal vereist vereist, zoals een geparametriseerde TOP telling, roep bindValue() dan met PDO::PARAM_INT en roep execute() dan zonder array.
Bind waarden zonder de query te wijzigen
Een parametermarker stelt een waarde voor, niet een tabelnaam, kolomnaam, trefwoord of sorteerrichting. Zet geen aanhalingstekens om ? heen. Voor een dynamische identifier of ASC/DESC, kies uit een door de applicatie gecontroleerde toestemmingslijst in plaats van onbetrouwbare tekst aan elkaar te koppelen. Voor een IN lijst geef je één opsommingsteken per waarde.
| Requirement | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Waarden binden voor één uitvoering | Geef de parameterarray door aan sqlsrv_query(). |
Geef een array door naar execute() na prepare(), of bind eerst de waarden. |
| Hergebruik de huidige waarde van een variabele | Neem &$variable op in de array die aan sqlsrv_prepare() wordt geleverd. |
Call bindParam() met de variabele, dan execute() zonder array. PHP geeft de variabele als referentie door; voeg & niet toe op de aanroeplocatie. |
| Bind een waarde op het moment van binding | Gebruik een waarde in de parameterarray voor de uitvoering. | Roep bindValue(); latere wijzigingen in de oorspronkelijke variabele veranderen die boundwaarde niet. |
| Geef een geheel getal op | Gebruik een parameterdescriptor met SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, en SQLSRV_SQLTYPE_INT wanneer een expliciet type nodig is. |
Koppel met PDO::PARAM_INT. Positioneel bindParam() en bindValue() indexen beginnen bij 0, niet 1. |
SQL verzenden NULL |
Bind PHP null, met een expliciet SQL-type wanneer vereist door de operatie. |
Binden met PDO::PARAM_NULL. |
| Uitvoerparameters ontvangen | Gebruik een gerefereerde variabele met SQLSRV_PARAM_OUT of SQLSRV_PARAM_INOUT. |
Gebruik bindParam() met PDO::PARAM_INPUT_OUTPUT en het vereiste type en lengte. |
Houd de gerefereerde variabelen actief tijdens het uitvoeren van de prepared statement. Het SQLSRV-programma verandert de bound-variabele in plaats van de parameterarray te vervangen. Het PDO-programma roept execute() bewust zonder array aan na binding; combineer dat patroon niet met array-gebaseerde uitvoering.
Outputwaarden van opgeslagen procedures vereisen hun eigen afhandeling, inclusief het afhandelen van de resultaten van de procedure. Leid geen output-parameter gedrag af uit deze input-only voorbeelden. Voor meer informatie, zie Directionele parameters gebruiken.
Configureren van uitvoerings- en ophaalgedrag
| Setting | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Time-out bij uitvoering |
QueryTimeout in de array met instructieopties. |
PDO::SQLSRV_ATTR_QUERY_TIMEOUT op de verbinding of instructie. |
| Benoemde resultaatsleutels |
SQLSRV_FETCH_ASSOC doorgegeven aan sqlsrv_fetch_array(). |
PDO::FETCH_ASSOC doorgegeven aan een fetch-methode of ingesteld als de standaard fetch-modus van de verbinding. |
| Alleen-doorstuurresultaten | Standaardcursor; haal in volgorde. | Standaardcursor; haal in volgorde. |
| Client-gebufferde resultaten |
Scrollable => SQLSRV_CURSOR_CLIENT_BUFFERED. |
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL met PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED. |
| Directe versus voorbereide uitvoering | Geen PDO-directquery-attribuut. Kies de gecombineerde sqlsrv_query() aanroep of het expliciete prepare/execute-paar. |
PDO::SQLSRV_ATTR_DIRECT_QUERY kiest directe uitvoering in plaats van de standaard voorbereide uitvoering van de driver. |
| Emulatie van parameters | Geen PDO-emulatie-attribuut. |
PDO::ATTR_EMULATE_PREPARES is los van het direct-query-attribuut. Gebruik het niet als vervanging voor het binden van de juiste types. |
De voorbeelden leveren kleine resultaten op.
fetchAll() laadt elke rij in het PHP-geheugen; gebruik een fetch-lus voor een groot resultaat. Een query die geen matches teruggeeft, is geen uitvoeringsfout. SQLSRV rapporteert eindresultaat als null van sqlsrv_fetch_array(); PDO rapporteert het als false van fetch(). Een SQL NULL binnen een opgehaalde rij blijft PHP null.
Gebruik geen SELECT aantal rijen als je enige succescheck. Forward-only cursors bieden niet dezelfde mogelijkheden voor het aantal rijen als gebuffte of scrollbare cursors. Haal de rijen op en tel die je nodig hebt, of gebruik een aparte COUNT query. Voor cursor-specifieke opties en beperkingen, zie Specificeer een cursortype en selecteer rijen.
Behandel mislukkingen en eindresultaten
Controleer SQLSRV prepare-, execute- en fetchbewerkingen apart. Een succesvolle prepare-bewerking bewijst niet dat de uitvoering zal slagen: de server kan parameterwaarden, permissies of de instructie tijdens de uitvoering weigeren. Leg sqlsrv_errors() onmiddellijk vast wanneer een bewerking false retourneert. SQLSRV behandelt veel waarschuwingen standaard als fouten, dus inspecteer de volledige collectie.
Voor PDO worden verbindingsfouten en databasefouten in uitzonderingsmodus als PDOException opgeworpen. Controleer de SQLSTATE- en driverfoutinformatie in beveiligde toepassingsdiagnostiek; geef geen uitzonderingstekst of inloggegevens terug in een HTTP-respons.
prepare() slagen is geen bewijs dat de instructie al is uitgevoerd.
| Symptom | Action |
|---|---|
| Elke uitvoering gebruikt de eerste waarde | Voor SQLSRV bind je een variabele via referentie. Gebruik voor PDO bindParam() voor een veranderende variabele of roep bindValue() aan voor elke nieuwe waarde. |
Een numerieke parameter wordt afgewezen, zoals een TOP aantal |
Bind expliciet het vereiste integer-type. PDO execute([$value]) gebruikt stringparameters, zelfs als de PHP-waarde een geheel getal is. |
| Een tweede opdracht rapporteert resultaten in behandeling | Consumeer de resultaten of geef ze vrij voordat je de verbinding opnieuw gebruikt. Voor PDO, gebruik closeCursor() wanneer je het resterende resultaat niet nodig hebt. |
| De verwachte outputparameters zijn niet veranderd | Voltooi alle procedureresultaten en verifieer de parameterrichting, PHP-type en de lengte van de outputbuffer. |
| Het geheugengebruik neemt toe met de grootte van het resultaat | Vervang fetchAll() of onnodige clientbuffering door sequentiële fetching. |
De voorbeelden maken hun statements vrij en geven hun verbindingen vrij in finally. Ze beginnen geen transactie. Gebruik een expliciete transactie wanneer meerdere schrijfopdrachten ofwel samen moeten committen of allemaal teruggerolld moeten worden. Het hergebruiken van een prepared statement groepeert de schrijfopdrachten niet in een transactie.
Verschillen in doel en implementatie
De prepare/execute-API's en PHP-referentieregels behoren tot de extensies en PHP/PDO. Het SQL-doel bepaalt welke T-SQL-statements en types worden ondersteund, en ODBC voert de onderliggende communicatie uit. Eenmalig voorbereiden kan herhaald werk verminderen, maar het garandeert geen specifiek serveruitvoeringsplan of versnelling.
De invoerbindingspatronen zijn van toepassing op SQL Server, Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics, SQL database in Microsoft Fabric en Warehouse in Microsoft Fabric. Deze programma's gebruiken SQL-authenticatie bij SQL Server. Voor Azure-onboarding geef je de voorkeur aan Microsoft Entra-authenticatie. Beide Fabric-producten vereisen dit, en Warehouse vereist ook het uitschakelen van Multiple Active Result Sets (MARS). Controleer de ondersteuning van het geselecteerde doelwit voor schemawijzigingen, transacties en opgeslagen procedures voordat je SQL Server-code hergebruikt. Voor verschillen tussen endpoints en authenticatie, zie Azure en Fabric connections.