Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Mindkét illesztőprogram egyszer futtathat egy lekérdezést, vagy előkészíthet egy lekérdezést ismételt végrehajtáshoz. Használj paramétereket a felhasználók által megadott értékekhez, még akkor is, ha csak egyszer futtatsz lekérdezést.
Válaszd ki a végrehajtási API-t külön attól, hogyan hozod az eredményeket. Egy lekérdezés előkészítése nem hozza le a sorokat, és az eredmény pufferelése nem teszi paraméterezetté a lekérdezést. A következő példák egyszer készítenek elő egy csak olvasható lekérdezést, kétszer futtatják különböző értékekkel, és minden eredményt a következő végrehajtás előtt fogyasztanak.
| Kivitelezési stílus | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Futtasson le egy lekérdezést egyszer, paraméterek nélkül | sqlsrv_query | PDO::query az eredményekért, vagy PDO::exec az érintett sorok számához |
| Futtasson egy lekérdezést paraméterekkel | sqlsrv_query($conn, $sql, $params) |
PDO::prepare(), majd PDOStatement::execute() |
| Egyszer készítse elő, ismételten hajtsa végre különböző paraméterekkel | sqlsrv_prepare + sqlsrv_execute | PDO::prepare + PDOStatement::execute |
sqlsrv_query() egy hívásban előkészíti és végrehajtja, majd visszaad egy statement erőforrást.
sqlsrv_prepare() visszaad egy előkészített utasítást anélkül, hogy lefuttatná; minden végrehajtáshoz hívja meg a(z) sqlsrv_execute() függvényt. A PDO-k query() végrehajtják és visszaadnak PDOStatement, míg exec() az érintett sorok számát ad vissza eredményobjektum helyett. A(z) exec() sikeresen visszaadhatja a(z) 0 értéket, ezért a hibás visszatérési értéket a(z) === false értékkel hasonlítsa össze, ne a(z) if (!$count) értékkel.
PDO::query() nem fogad el paraméterértékek tömbjét. Az opcionális argumentumok konfigurálják a lekérést. Paraméterezett PDO_SQLSRV lekérdezésekhez használd prepare() és execute().
Az egyszeri előkészítés lehetővé teszi, hogy újrahasznosíts egy utasításazonosítót különböző értékekkel. Ez nem garantálja, hogy a szerver soha nem fordítja újra a végrehajtási tervet. A PDO_SQLSRV alapértelmezés szerint előkészített végrehajtást használ, beleértve a PDO::query(); ezt a külön beállítást a közvetlen lekérdezés attribútuma szabályozza.
Készíts elő egyszer, és végezz el ismételten
Ezek különálló, teljes parancssori programok. Telepítsd és töltsd be a kiválasztott kiegészítőt, és beállítsd SQL_SERVER, SQL_DATABASE, SQL_USER, és SQL_PASSWORD a PHP folyamatkörnyezetbe. Használj egy SQL Server tesztadatbázist és egy szerver tanúsítványt, amelyet az ügyfél megbízható. A környezet beállításáról és jelszó nélküli alternatívákról lásd: Csatlakozás szerverhez.
Tárold a tényleges adatbázis nevét, felhasználónevet és jelszót a környezeti változókban. Mindkét program egyszer elkerüli ezeket az értékeket azzal, hogy megduplázza a záró tartókat, és minden értéket fogszabályzóba zár, ahogy azt a PHP illesztőgép ODBC-stílusú kapcsolatkezelése megköveteli. A kapcsolódási értékek escape-elése különálló a lekérdezési paraméterek kötésétől.
A programok két soron keresztül hajtanak végre Transact-SQL (T-SQL) lekérdezést anélkül, hogy táblázatot hoznának létre vagy adatokat változtatnának. Ments el minden programot a saját .php fájljába, és futtasd a(z) php <file> paranccsal. Mintaadatbázis nem szükséges.
SQLSRV
Adja át a(z) $productId elemet hivatkozással a(z) &$productId használatával. Ezután mindegyik sqlsrv_execute() használja a jelenlegi értékét.
SQLSRV_FETCH_ASSOC egy oszlopnév alapján kulcsolt tömböt ad vissza. Az null eredmény azt jelenti, hogy nincs több sor; false hibát jelez.
<?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
Kösd össze $productId egyszer a bindParam() használatával. Mindegyik execute() a jelenlegi értékét mutatja.
PDO::PARAM_INT megadja a paraméter PHP/PDO kötési típusát; nem szabályozza az eredményből lekért oszlopok PHP-típusát. Állítsuk be a kivétel módot, hogy egy adatbázishiba megszakítsa a végrehajtást, ahelyett, hogy üres eredménynek tűnne.
<?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;
}
Minden példa a következőket nyomtatja:
Bike
Helmet
A tömbben a PDO-knak execute() továbbított értékeket úgy kezelik, mint PDO::PARAM_STR. Ha az SQL egész számparamétert igényel, például paraméterezett TOP darabszámot, hívja meg a(z) bindValue() metódust a(z) PDO::PARAM_INT használatával, majd tömb nélkül hívja meg a(z) execute() metódust.
Értékek kötése lekérdezés megváltoztatása nélkül
A paraméterjelölő egy értéket képvisel, nem táblanévet, oszlopnevet, kulcsszót vagy rendezési irányt. Ne helyezz idézőjeleket ? köré. Dinamikus azonosító esetén vagy ASC/DESC, válassz egy alkalmazás által vezérelt engedélyezett listából a nem megbízható szöveg összekötése helyett. Egy IN listához értékenként adj meg egy jelölőt.
| Requirement | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Értékek kötése egy végrehajtásra | A paramétertömböt továbbítsuk a sqlsrv_query() részére. |
Továbbítsunk egy tömböt prepare() után a execute() számára, vagy először kössük meg az értékeket. |
| Használd újra egy változó aktuális értékét | Foglalja bele a(z) &$variable elemet a sqlsrv_prepare() számára megadott tömbbe. |
A változóval hívjuk bindParam() , majd execute() tömb nélkül. A PHP referenciaként adja át a változót; ne add meg a(z) & elemet a hívás helyén. |
| Köss egy értéket a kötés pillanatában | Használj a paramétertömb egyik értékét a végrehajtáshoz. | Call bindValue(); az eredeti változó későbbi módosításai nem változtatják meg ezt a kötött értéket. |
| Adjon meg egy egész számot | Használj paraméterleírót , SQLSRV_PARAM_INSQLSRV_PHPTYPE_INT, , és SQLSRV_SQLTYPE_INT amikor explicit típusra van szükség. |
Kösd össze PDO::PARAM_INT. A pozicionális bindParam() és bindValue() indexek 1-nél kezdődnek, nem 0-nál. |
SQL küldése NULL |
A PHP-t null kifejezett SQL-típussal kösd meg, ha a művelet megköveteli. |
Kötés PDO::PARAM_NULL. |
| Kimeneti paraméterek fogadása | Használj egy hivatkozott változót vagy SQLSRV_PARAM_OUTSQLSRV_PARAM_INOUT. |
Használd bindParam()PDO::PARAM_INPUT_OUTPUT a szükséges típust és hosszt. |
Tartsd életben a hivatkozott változókat az előkészített utasítás végrehajtása közben. Az SQLSRV program a kötött változót változtatja a paramétertömb lecserélése helyett. A PDO program szándékosan execute() hív tömb nélkül a kötés után; ne keverd össze ezt a mintát a tömbalapú végrehajtással.
A tárolt eljárások kimeneti értékeinek saját kezelése szükséges, beleértve az eljárás eredményeinek befejezését is. Ne következtess kimenet-paraméter viselkedést ezekből a csak bemeneti példákból. További információért lásd: Irányító paraméterek használata.
Végrehajtás és lekérési viselkedés konfigurálása
| Setting | SQLSRV | PDO_SQLSRV |
|---|---|---|
| Végrehajtási időkorlát |
QueryTimeout az állítás opciók tömbjében. |
PDO::SQLSRV_ATTR_QUERY_TIMEOUT a kapcsolatról vagy állításról. |
| Nevelt eredménykulcsok |
SQLSRV_FETCH_ASSOCÁtadva .sqlsrv_fetch_array() |
PDO::FETCH_ASSOC átadva egy fetch metódusnak vagy a kapcsolat alapértelmezett fetch módjának. |
| Csak előre bejárható eredmények | Alapértelmezett kurzor; lekérés sorrendben. | Alapértelmezett kurzor; lekérés sorrendben. |
| Kliens-pufferelt eredmények |
Scrollable => SQLSRV_CURSOR_CLIENT_BUFFERED. |
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL vel PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED. |
| Közvetlen kontra előkészített végrehajtás | Nincs PDO közvetlen lekérdezési attribútum. Válasszuk a kombinált sqlsrv_query() hívást vagy az explicit előkészítő/végrehajtó párt. |
PDO::SQLSRV_ATTR_DIRECT_QUERY a közvetlen végrehajtást választja az illesztőprogram alapértelmezett előkészített végrehajtása helyett. |
| Paraméteremuláció | Nincs PDO emulációs attribútum. |
PDO::ATTR_EMULATE_PREPARES külön a direct-query attribútumtól. Ne használd a megfelelő típusok kötésének helyettesítésére. |
A példák kis eredményeket adnak vissza.
fetchAll() minden sort betölt PHP memóriába; használj fetch loopot egy nagy eredményhez. Egy lekérdezés, amely nem talált egyezést, nem végrehajtási hiba. Az SQLSRV az eredmény végét null értékként jelzi a(z) sqlsrv_fetch_array() helyett; a PDO pedig false értékként jelzi a(z) fetch() helyett. A lekért soron belüli SQL NULL PHP null marad.
Ne használd a SELECT sorok számát az egyetlen siker próbájaként. Az előre csak előre használható kurzorok nem biztosítanak ugyanolyan képességet a sorok számának meghatározására, mint a pufferelt vagy görgethető kurzorok. Szerezd meg és számold meg a szükséges sorokat, vagy használj külön COUNT lekérdezést. A kurzorspecifikus beállításokkal és korlátozásokkal kapcsolatban lásd: Kurzortípus megadása és sorok kiválasztása.
Hibák kezelése és végső eredmények
Ellenőrizd az SQLSRV prepare, execute és fetch műveleteket külön-külön. Egy sikeres előkészítés nem bizonyítja, hogy a végrehajtás sikeres lesz: a szerver a végrehajtáskor elutasíthatja a paraméterértékeket, jogosultságokat vagy az utasítást. Azonnal rögzítsd sqlsrv_errors() , amikor egy művelet visszatér false. Az SQLSRV alapértelmezés szerint sok figyelmeztetést hibáként kezel, ezért vizsgáld meg a teljes gyűjteményt.
PDO esetén a kapcsolati hibák és adatbázis-hibák kivétel módban kivételt dobnak PDOException. Ellenőrizd annak SQLSTATE-értékét és a driver hibaadatait az alkalmazás védett diagnosztikai adataiban; ne küldj vissza kivételszöveget vagy hitelesítő adatokat HTTP-válaszban.
prepare() A sikeres lefutás nem bizonyíték arra, hogy az utasítás már lefutott.
| Tünet | Action |
|---|---|
| Minden végrehajtás az első értéket használja | SQLSRV esetén köss egy változót referenciaként. PDO-hoz használj bindParam() egy változó értékű változóhoz, vagy hívd meg a bindValue() függvényt minden egyes új értékhez. |
Egy numerikus paramétert elutasítunk, például egy TOP darabszámot |
Kifejezetten adja meg a szükséges egész szám típusát. A PDO execute([$value]) string paramétereket használ, még akkor is, ha a PHP érték egész szám. |
| Egy második parancsnokság jelentést tesz a váratlan eredményekről | Használd fel az eredményeket vagy add ki őket, mielőtt újra használnád a kapcsolatot. PDO-hoz akkor használd closeCursor() , amikor nincs szükséged a maradék eredményre. |
| A várható kimeneti paraméterek nem változtak | Töltse ki az összes eljárás eredményét, ellenőrizze a paraméterirányt, a PHP típust és a kimenet-puffer hosszát. |
| A memóriahasználat az eredménymérettel növekedik | Helyettesítsd fetchAll() vagy a felesleges klienspufferezést szekvenciális behívással. |
A példák felszabadítják az utasításokat, és lezárják a kapcsolataikat a(z) finally elemben. Ők nem kezdenek tranzakciót. Használj explicit tranzakciót, amikor több írásnak vagy együtt kell véglegesülnie, vagy mind vissza kell vonni. Egy előkészített utasítás újrahasznosítása nem csoportosítja az írásokat tranzakcióba.
Cél és megvalósítási különbségek
A prepare/execute API-k és a PHP-referenciára vonatkozó szabályok a kiterjesztésekhez és a PHP/PDO-hoz tartoznak. Az SQL célpont dönti el, mely T-SQL utasítások és típusok támogatottak, és az ODBC végzi az alapul szolgáló kommunikációt. Az egyszeri előkészület csökkentheti az ismételt munkát, de nem garantálja egy adott szerver végrehajtási tervet vagy gyorsítást.
Az input-binding minták alkalmazhatók SQL Server, Azure SQL Database, Azure SQL Managed Instance, Azure Synapse Analytics, SQL database in Microsoft Fabric és Warehouse in Microsoft Fabric. Ezek a programok SQL hitelesítést használnak az SQL Serverhez. Az Azure-ba történő bevezetéshez részesítsd előnyben a Microsoft Entra-hitelesítést. Mindkét Fabric termék megköveteli ezt, és a Warehouse esetében is le kell tiltani a Multiple Active Result Sets (MARS) funkciót. Ellenőrizd, hogy a kiválasztott célpont támogatja-e a sémamódosításokat, tranzakciókat és tárolt eljárásokat, mielőtt újra felhasználnád az SQL Server kódot. A végpontok és hitelesítési különbségek esetén lásd: Azure és Fabric kapcsolatok.