Yürütme işlevlerini karşılaştırma

PHP sürücüsünü indirme

Her iki sürücü de bir komutu bir kez çalıştırabilir veya tekrarlı yürütme için bir komut hazırlayabilir. Kullanıcılar tarafından sağlanan değerler için parametreler kullanın, sorguyu sadece bir kez çalıştırsanız bile.

Sonuçları nasıl getirdiğinizden ayrı olarak yürütme API'sini seçin. Bir sorgu hazırlamak onun satırlarını getirmez ve bir sonucu tamponlamak sorguyu parametreli yapmaz. Aşağıdaki örnekler, salt okunur bir sorgu bir kez hazırlar, farklı değerlerle iki kez çalıştırır ve her sonucu bir sonraki yürütmeden önce tüketir.

Yürütme stili SQLSRV PDO_SQLSRV
Parametre olmadan bir sorgu çalıştırın sqlsrv_query PDO::query sonuçlar için veya PDO::exec etkilenen satır sayıları için
Parametrelerle bir sorgu bir kez çalıştırın sqlsrv_query($conn, $sql, $params) PDO::prepare() ve ardından PDOStatement::execute()
Bir kez hazırlanın, farklı parametrelerle tekrar tekrar çalıştırın sqlsrv_prepare + sqlsrv_execute PDO::prepare + PDOStatement::execute

sqlsrv_query() tek bir çağrıda hazırlar ve çalıştırır ve bir komut deyimi kaynağı döndürür. sqlsrv_prepare() bir ifade kaynağını çalıştırmadan döndürür; her çalıştırma için sqlsrv_execute() çağrısını yapın. PDO'nun query() yöntemi PDOStatement çalıştırır ve döndürür, exec() ise sonuç nesnesi yerine etkilenen satır sayısını döndürür. Başarılı exec(), 0 döndürebilir; bu yüzden başarısız dönüşü if (!$count) ile değil, === false ile karşılaştırın.

PDO::query() parametre değerlerinden oluşan bir diziyi kabul etmez. İsteğe bağlı argümanları getirmeyi yapılandırır. Parametreli PDO_SQLSRV sorguları için execute() ve prepare() kullanın.

Bir kez hazırlamak, farklı değerlerle bir ifade tutamacını yeniden kullanmanızı sağlar. Bu, sunucunun yürütme planını asla yeniden derlemediği garantisi değildir. PDO_SQLSRV, varsayılan olarak, PDO::query() dahil hazırlanmış yürütmeyi kullanır; bu ayrı seçimi direct-query özniteliği denetler.

Bir kez hazırlanın ve tekrar tekrar çalıştırın

Bunlar ayrı, tam komut satırı programlarıdır. Seçilen uzantıyı yükleyin ve yükleyin, ardından PHP işlem ortamında SQL_DATABASE, SQL_USER, SQL_PASSWORD ve SQL_SERVER ayarlayın. Bir SQL Server test veritabanı ve istemcinin güvendiği bir sunucu sertifikası kullanın. Ortam kurulumu ve şifresiz alternatifler için Sunucuya Bağlanma bölümünü inceleyebilirsiniz.

Gerçek veritabanı adı, kullanıcı adı ve şifreyi ortam değişkenlerinde sakla. Her iki program da PHP sürücüsünün ODBC tarzı bağlantı işleme sisteminde gerektiği gibi, kapanış süslü parantezlerini iki katına çıkarıp her değeri süslü parantez içine alarak bu değerleri bir kez escape eder. Bağlantı değerlerinin escape edilmesi, sorgu parametrelerini bağlamadan ayrıdır.

Programlar, tablo oluşturmadan veya veri değiştirmeden iki satırlık satır içi veri üzerinde bir Transact-SQL (T-SQL) sorgusu yürütür. Her programı kendi .php dosyasına kaydedin ve bunu php <file> ile çalıştırın. Örnek bir veritabanı gerekmemektedir.

SQLSRV

$productId ögesini &$productId ile başvuruya göre geçirin. Her biri sqlsrv_execute() mevcut değerini kullanır. SQLSRV_FETCH_ASSOC sütun adıyla anahtarlanmış bir diziyi döndürür. null sonucu, artık satır kalmadığı anlamına gelir; false hata olduğunu gösterir.

<?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

bindParam() ile $productId bir kez bağlayın. Her biri execute() mevcut değerini okur. PDO::PARAM_INT parametrenin PHP/PDO bağlama tipini belirler; sonuçtan alınan PHP tipli sütunları kontrol etmez. İstisna modu ayarlayın, böylece veritabanı hatası boş bir sonuç olarak karıştırmak yerine yürütmeyi kessin.

<?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;
}

Her örnek şunları yazıyor:

Bike
Helmet

PDO'nun execute() öğesine iletilen bir dizideki değerler PDO::PARAM_STR olarak ele alınır. SQL bir tamsayı parametresi gerektirdiğinde, örneğin parametreli TOP sayım parametresi, bindValue() ile PDO::PARAM_INT çağrısını yapın ve ardından bir dizi olmadan execute() çağrısını yapın.

Sorguyu değiştirmeden değerleri bağlama

Parametre belirticisi, bir tablo adı, sütun adı, anahtar kelime veya sıralama yönü değil, bir değeri temsil eder. ? etrafına tırnak işareti koymayın. Dinamik bir tanımlayıcı veya ASC/DESCiçin, güvenilir olmayan metni birleştirmek yerine uygulama kontrolündeki izin listesinden seçin. Bir IN liste için, her değer için bir işaret verin.

Requirement SQLSRV PDO_SQLSRV
Tek bir yürütme için değerleri bağlama Parametre dizisini sqlsrv_query() öğesine iletin. Bir diziyi prepare() sonrasında execute() öğesine iletin veya önce değerleri bağlayın.
Bir değişkenin mevcut değerini yeniden kullanın sqlsrv_prepare() öğesine sağlanan diziye &$variable dahil edin. Değişkenle çağrı bindParam() , sonra execute() dizi olmadan. PHP değişkeni referansla geçirir; & öğesini çağrı noktasında eklemeyin.
Bağlama anında bir değeri bağlayın Uygulama için parametre dizisinde bir değer kullanın. Call bindValue(); orijinal değişkene yapılan sonraki değişiklikler o bağlanan değeri değiştirmez.
Bir tamsayı girdisi belirtin Açık bir tür gerektiğinde , SQLSRV_PARAM_INSQLSRV_PHPTYPE_INT, ile bir parametre tanımlayıcısı kullanın.SQLSRV_SQLTYPE_INT Bağlanın .PDO::PARAM_INT Pozisyonsal bindParam() ve bindValue() indeksler , ile 1başlar, değil 0.
SQL Gönder NULL İşlem gerektirdiğinde, PHP'yi null ile açık bir SQL türüne bağlayın. Bağla PDO::PARAM_NULL.
Çıkış parametrelerini alın Referanslı bir değişken kullanın SQLSRV_PARAM_OUT ve .SQLSRV_PARAM_INOUT Gerekli tip ve uzunlukla kullanın bindParam()PDO::PARAM_INPUT_OUTPUT .

Hazırlanmış ifadeyi çalıştırırken referans edilen değişkenleri canlı tutun. SQLSRV programı, parametre dizisini değiştirmek yerine bağlı değişkeni değiştirir. PDO programı, bağlamadan sonra kasıtlı olarak dizi olmadan çağrı execute() yapar; bu deseni dizi tabanlı yürütme ile karıştırmayın.

Depolanan prosedürlerden çıkan çıktı değerleri, prosedürün sonuçlarının tamamlanması da dahil olmak üzere kendi işlenmesini gerektirir. Bu sadece girdi gerektiren örneklerden çıktı-parametre davranışı çıkarmayın. Daha fazla bilgi için bkz. Yönlü parametreleri kullanmak.

Çalıştırma ve getirme davranışını yapılandır

Setting SQLSRV PDO_SQLSRV
Infaz molası QueryTimeout Seçenekler dizisinde ifade bulunuyor. PDO::SQLSRV_ATTR_QUERY_TIMEOUT bağlantıda veya komutta.
Isimlendirilmiş sonuç anahtarları SQLSRV_FETCH_ASSOC, sqlsrv_fetch_array() öğesine aktarıldı. PDO::FETCH_ASSOC bir fetch yöntemine veya bağlantının varsayılan getirme modu olarak ayarlanmış bir yönteme aktarılır.
Sadece ileri sonuçlar Varsayılan imleç; getir sırasıyla alın. Varsayılan imleç; sırayla getir.
İstemci tamponlu sonuçlar Scrollable => SQLSRV_CURSOR_CLIENT_BUFFERED. PDO::ATTR_CURSOR => PDO::CURSOR_SCROLLile PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED.
Doğrudan ve hazırlıklı infaz PDO doğrudan sorgu özniteliği yok. Birleşik sqlsrv_query() çağrıyı veya açık hazırla/çalıştırma çiftini seçin. PDO::SQLSRV_ATTR_DIRECT_QUERY doğrudan çalıştırmayı sürücünün varsayılan hazırlıklı çalıştırması yerine seçer.
Parametre öykünmesi PDO emülasyon özelliği yok. PDO::ATTR_EMULATE_PREPARES doğrudan sorgu özniteliğinden ayrıdır. Doğru türleri bağlamanın yerine onu kullanmayın.

Örnekler küçük sonuçlar veriyor. fetchAll() her satırı PHP belleğe yükler; büyük bir sonuç için bir fetch döngüsü kullanın. Eşleşme vermeden gelen bir sorgu bir yürütme hatası değildir. SQLSRV, sonucun sonunu sqlsrv_fetch_array() konumundan null olarak bildirir; PDO ise bunu false konumundan fetch() olarak bildirir. Alınan bir satırdaki SQL NULL, PHP null olarak kalır.

Başarı kontrolü olarak yalnızca satır SELECT sayısını kullanmayın. Yalnızca ileri cursor'lar, tamponlu veya kaydırılabilir cursor'lar ile aynı satır sayısı yeteneklerini sağlamaz. İhtiyacınız olan satırları getirin ve sayın ya da ayrı COUNT bir sorgu kullanın. İmlece özgü seçenekler ve sınırlamalar için bkz. İmleç tipi belirt ve satır seç.

Başarısızlıkları ve tamamlama sonuçlarını ele alın

SQLSRV prepare, execute ve fetch işlemlerini ayrı ayrı kontrol edin. Başarılı bir prepare, yürütmenin başarılı olacağını kanıtlamaz: sunucu, yürütme sırasında parametre değerlerini, izinleri veya ifadeyi reddedebilir. Bir işlem sqlsrv_errors() döndürdüğünde false hemen yakalayın. SQLSRV birçok uyarıyı varsayılan olarak hata olarak kabul eder, bu yüzden tüm koleksiyonu inceleyin.

PDO için, bağlantı hataları ve istisna modundaki veritabanı hataları PDOException fırlatır. Korunan uygulama tanılamalarında SQLSTATE ve sürücü hata bilgilerini inceleyin; HTTP yanıtında istisna metni veya kimlik bilgilerini geri göndermeyin. prepare() Başarılı olmak, ifadenin zaten yürütüldüğüne dair kanıt değildir.

Belirti Action
Her çalıştırmada ilk değer kullanılır SQLSRV için, bir değişkeni referans yoluyla bağlayın. PDO için, değişen bir değişken için bindValue() kullanın veya her yeni değer için bindParam() çağırın.
Sayısal bir parametre, örneğin bir TOP count, reddedilir Gerekli tam sayı tipini açıkça bağlayın. PDO execute([$value]) , PHP değeri tam sayı olsa bile dize parametreleri kullanır.
İkinci bir komut, bekleyen sonuçları rapor eder Bağlantıyı tekrar kullanmadan önce sonuçları tüketin veya serbest bırakın. PDO için, kalan sonuca ihtiyacınız olmadığında kullanın closeCursor() .
Beklenen çıkış parametreleri değişmedi Tüm yordam sonuçlarını eksiksiz girin ve parametre yönünü, PHP tipini ve çıktı-tampon uzunluğunu doğrulayın.
Bellek kullanımı sonuç boyutuyla birlikte artar fetchAll() veya gereksiz istemci arabelleğe almayı sıralı getirmeyle değiştirin.

Örnekler, ifadelerinin serbest bırakılmasını ve bağlantılarının kapatılmasını finally sağlar. İşlem başlatmazlar. Birden fazla yazmanın ya birlikte onaylanması ya da tamamen geri alınması gerektiğinde, açık bir işlem kullanın. Hazırlanmış ifadeyi tekrar kullanmak, yazma işlemlerini bir işlem altında gruplamaz.

Hedef ve uygulama farklılıkları

Hazırla/çalıştır API'leri ve PHP referans kuralları uzantılara ve PHP/PDO'ya aittir. SQL hedefi, hangi T-SQL ifadelerinin ve türlerinin destekleneceğine karar verir ve ODBC temel iletişimi gerçekleştirir. Bir kez hazırlık yapmak tekrarlanan işleri azaltabilir, ancak belirli bir sunucu yürütme planı veya hızlandırma garantisi vermez.

Giriş bağlama düzenleri SQL Server, Azure SQL Veritabanı, Azure SQL Yönetilen Örneği, Azure Synapse Analytics, Microsoft Fabric'teki SQL veritabanı ve Microsoft Fabric'teki Warehouse için geçerlidir. Bu programlar SQL Server için SQL kimlik doğrulamasını kullanır. Azure onboarding için Microsoft Entra kimlik doğrulaması'nı tercih edin. Her iki Fabric ürünü de bunu gerektirir ve Warehouse ayrıca Çoklu Aktif Sonuç Setlerini (MARS) devre dışı bırakmayı gerektirir. SQL Server kodunu tekrar kullanmadan önce seçilen hedefin şema değişiklikleri, işlemler ve depolanmış prosedürler desteğini kontrol edin. Uç nokta ve kimlik doğrulama farklılıkları için Azure ve Fabric bağlantılarına bakınız.