Start · Sprachen · PHP · Referenz · sqlsrv_send_stream_data

sqlsrv_send_stream_data

Funktion

Sendet Daten aus Parameter-Streams paketweise an den SQL-Server und gibt <code>true</code> bei Erfolg zurück.

seit PHP 1.0 Kategorie: db

Signatur

sqlsrv_send_stream_data(resource $stmt): bool

Beschreibung

sqlsrv_send_stream_data() gehört zum Microsoft SQL Server Driver für PHP (SQLSRV-Erweiterung) und ermöglicht es, große Datenmengen aus PHP-Streams (z. B. geöffnete Dateien oder In-Memory-Streams) schrittweise an den SQL Server zu übertragen. Standardmäßig werden Stream-Daten beim Aufruf von sqlsrv_execute() vollständig gesendet; mit sqlsrv_send_stream_data() kann dieses Verhalten manuell gesteuert werden.

Die Funktion ist besonders nützlich, wenn die Option SendStreamParamsAtExec beim Erstellen des Statements auf false gesetzt wurde. In diesem Fall müssen die Stream-Daten durch wiederholten Aufruf von sqlsrv_send_stream_data() in mehreren Paketen gesendet werden, bis false zurückgegeben wird – was signalisiert, dass alle Daten übermittelt wurden.

Typische Anwendungsfälle sind das Einfügen oder Aktualisieren großer Binärdaten (z. B. Bilder, Dokumente) oder langer Texte in SQL-Server-Spalten vom Typ VARBINARY(MAX), VARCHAR(MAX) oder NVARCHAR(MAX).

  • Ein Rückgabewert von true bedeutet, dass noch weitere Daten gesendet werden müssen.
  • Ein Rückgabewert von false bedeutet entweder, dass alle Daten vollständig übertragen wurden, oder dass ein Fehler aufgetreten ist – beides muss mit sqlsrv_errors() unterschieden werden.

Parameter

Name Typ Default Beschreibung
$stmt Pflicht resource Ein gültiges Statement-Ressource-Handle, das mit sqlsrv_prepare() erstellt und mit sqlsrv_execute() ausgeführt wurde. Das Statement muss mindestens einen Stream-Parameter enthalten, und SendStreamParamsAtExec sollte auf false gesetzt sein.

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn noch weitere Stream-Daten gesendet werden müssen. Gibt false zurück, wenn alle Daten übertragen wurden oder ein Fehler aufgetreten ist. Um einen Fehler von einem erfolgreichen Abschluss zu unterscheiden, muss sqlsrv_errors() aufgerufen werden.

Beispiele

Großes Bild als Stream in SQL Server einfügen

<?php
$serverName = 'localhost';
$connectionInfo = [
    'Database' => 'TestDB',
    'UID'      => 'sa',
    'PWD'      => 'geheim'
];

$conn = sqlsrv_connect($serverName, $connectionInfo);
if (!$conn) {
    die('Verbindung fehlgeschlagen: ' . print_r(sqlsrv_errors(), true));
}

// Datei als Stream öffnen
$fileStream = fopen('/pfad/zur/datei/bild.jpg', 'rb');
if (!$fileStream) {
    die('Datei konnte nicht geöffnet werden.');
}

$sql = 'INSERT INTO Bilder (Name, Daten) VALUES (?, ?)';
$params = [
    'Mein Bild',
    [
        $fileStream,
        SQLSRV_PARAM_IN,
        null,
        SQLSRV_SQLTYPE_VARBINARY('max')
    ]
];

// Statement vorbereiten, Streams NICHT sofort senden
$stmt = sqlsrv_prepare($conn, $sql, $params, ['SendStreamParamsAtExec' => false]);
if (!$stmt) {
    die('Prepare fehlgeschlagen: ' . print_r(sqlsrv_errors(), true));
}

// Statement ausführen (ohne Stream-Daten)
if (sqlsrv_execute($stmt) === false) {
    die('Execute fehlgeschlagen: ' . print_r(sqlsrv_errors(), true));
}

// Stream-Daten paketweise senden
while (sqlsrv_send_stream_data($stmt)) {
    // Schleife läuft, bis alle Daten gesendet wurden
    echo 'Datenpaket gesendet...' . PHP_EOL;
}

// Prüfen, ob ein Fehler aufgetreten ist
if (sqlsrv_errors()) {
    echo 'Fehler beim Senden: ' . print_r(sqlsrv_errors(), true);
} else {
    echo 'Alle Stream-Daten erfolgreich übertragen.';
}

fclose($fileStream);
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
?>
Datenpaket gesendet... Datenpaket gesendet... Alle Stream-Daten erfolgreich übertragen.

In-Memory-Stream mit Text-Daten senden

<?php
$serverName = 'localhost';
$connectionInfo = [
    'Database' => 'TestDB',
    'UID'      => 'sa',
    'PWD'      => 'geheim'
];

$conn = sqlsrv_connect($serverName, $connectionInfo);
if (!$conn) {
    die('Verbindung fehlgeschlagen.');
}

// Großen Text als In-Memory-Stream simulieren
$textStream = fopen('php://memory', 'a+');
fwrite($textStream, str_repeat('Lorem ipsum dolor sit amet. ', 1000));
rewind($textStream);

$sql = 'INSERT INTO Dokumente (Titel, Inhalt) VALUES (?, ?)';
$params = [
    'Testdokument',
    [
        $textStream,
        SQLSRV_PARAM_IN,
        SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_CHAR),
        SQLSRV_SQLTYPE_NVARCHAR('max')
    ]
];

$stmt = sqlsrv_prepare($conn, $sql, $params, ['SendStreamParamsAtExec' => false]);
sqlsrv_execute($stmt);

// Alle Pakete senden
$pakete = 0;
while (sqlsrv_send_stream_data($stmt)) {
    $pakete++;
}

if (!sqlsrv_errors()) {
    echo "Stream-Übertragung abgeschlossen. Pakete gesendet: {$pakete}";
} else {
    echo 'Fehler: ' . print_r(sqlsrv_errors(), true);
}

fclose($textStream);
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
?>
Stream-Übertragung abgeschlossen. Pakete gesendet: 3

// Wichtig · Fallstricke

Fehlerunterscheidung: Da sqlsrv_send_stream_data() sowohl bei erfolgreichem Abschluss als auch bei einem Fehler false zurückgibt, muss nach der Schleife immer sqlsrv_errors() aufgerufen werden, um sicherzustellen, dass kein Fehler aufgetreten ist.

Voraussetzung: Die Option SendStreamParamsAtExec muss beim Aufruf von sqlsrv_prepare() auf false gesetzt sein. Andernfalls werden alle Stream-Daten bereits bei sqlsrv_execute() gesendet und sqlsrv_send_stream_data() hat keine Wirkung.

Paketgröße: Die Paketgröße pro Aufruf wird durch den Verbindungsparameter PacketSize beeinflusst (Standard: 4096 Bytes). Für sehr große Datenmengen empfiehlt sich eine größere Paketgröße zur Optimierung der Übertragungsgeschwindigkeit.

Sicherheit: Stellen Sie sicher, dass Eingaben, die in Stream-Parametern verarbeitet werden, validiert und ggf. auf Dateityp und Größe geprüft werden, um unerwünschte Datei-Uploads oder Ressourcenerschöpfung zu vermeiden.