2017-11-24 3 views
0

Ich habe PHP 5.3 mit der Erweiterung pdo_sqlsrv und einer MSSQL2008-Datenbank. Der folgende Code ruft Daten aus der Tabelle mit vorbereiteter Anweisung ab, alles funktioniert einwandfrei. Wenn ich die Anweisung jedoch mehrmals wiederhole, kann ich im SQL Server-Profil sehen, dass die vorbereitete Anweisung nicht wiederverwendet wird. Bei jeder SQL-Anfrage wird die Anweisung erneut vorbereitet.PHP PDO mit MSSQL verwendet keine vorbereitete Anweisung

$this->statement = $connection->prepare("SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = :textType;"); 
    $this->statement->bindValue(":textType", "URL"); 
    $this->statement->execute(); 
    $data = $this->statement->fetchAll(PDO::FETCH_ASSOC) or array(); 
    $this->statement->closeCursor(); 


    $this->statement->bindValue(":textType", "SYSTEM"); 
    $this->statement->execute(); 
    $data = $this->statement->fetchAll(PDO::FETCH_ASSOC) or array(); 
    $this->statement->closeCursor(); 

Der Grund für dieses Verhalten könnte in verschiedenen Stringlängen der Variablen $ textType liegen. Wie Sie in der Profilerliste sehen können, wird die gleiche Anweisung zweimal mit dem Datentyp des Eingabeparameters (nvarchar (6) und nvarchar (3)) vorbereitet.

SQL Server Profiler Protokolleintrag dieser Datenanforderungen:

declare @p1 int 
set @p1=2 
exec sp_prepexec @p1 output,N'@P1 nvarchar(3)',N'SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = @P1;',N'URL' 
select @p1 

declare @p1 int 
set @p1=3 
exec sp_prepexec @p1 output,N'@P1 nvarchar(6)',N'SELECT Lang,MemoryArea,ID,TextType,TextValue FROM CoreLanguage WHERE TextType = @P1;',N'SYSTEM' 
select @p1 

Wenn die Eingabezeichenfolge Daten immer gleich lang sind, wird die Anweisung vom SQL-Server wiederverwendet werden. Das wird jedoch selten der Fall sein ...

Weiß jemand, warum der SQL Server die bereits vorbereitete Anweisung nicht wiederverwenden kann? Oder wie könnte ich den Eingabeparameter @ P1 zu einem geeigneten Datentyp manipulieren, zum Beispiel nvarchar (40) (genauso wie die TextType-Spaltendefinition)?

Vielleicht gibt es eine treiberspezifische Option, die ich verpasst habe?

+0

Sie können versuchen, das PDO-Attribut 'PDO :: ATTR_EMULATE_PREPARES' auf false zu setzen. – Sammitch

+0

Ich habe versucht, das Attribut vor der Vorbereitung der Anweisung zu setzen: '$ connection-> setAttribute (PDO :: ATTR_EMULATE_PREPARES, false);' Dies hat das Ergebnis nicht geändert. Der Punkt ist, dass es funktioniert, aber nur, wenn die Parameter-String-Länge genau gleich ist. Andernfalls wird aufgrund der unterschiedlichen Parameterlänge von @ P1 eine neue vorbereitete Anweisung erstellt. – Tom

Antwort

0

Haben Sie versucht mit bindParam() statt bindValue()? Vielleicht kannst du es versuchen.

+0

Ja, ich habe es bereits mit bindParam versucht und auch seinen dritten Parameter PDO :: PARAM_STR. Das Ergebnis auf dem SQL-Server ist identisch. – Tom

Verwandte Themen