2014-01-17 7 views
5

Ich habe ein Projekt in Delphi 7 und ich verwende TAdoQuery.ParseSql();, um Parameter zu laden. Jetzt kompiliere ich es in XE4 und der Typ der Parameter ist manchmal falsch. Es ist wirklich ftInteger aber als ftSmallint erstellt. Was kann ich tun, um dieses Problem zu lösen? Meine Datenbank ist SQL Server 2008 R2.TAdoQuery.ParseSql funktioniert nicht in xe4

Tabellendefinition:

CREATE TABLE [dbo].[tblTest]( 
    [sysId] [int] IDENTITY(1,1) NOT NULL, 
    [Code] [nvarchar](50) NOT NULL, 
    [Name] [nvarchar](500) NOT NULL, 
CONSTRAINT [PK_tblTest] 
PRIMARY KEY CLUSTERED ([sysId] ASC) 
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
      ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
    ON [PRIMARY]) 
ON [PRIMARY] 

Beispieldaten:

INSERT INTO tblTest (Code, Name) VALUES ('a1', 'name1') 

Delphi-Code:

ADOQuery.SQL.Text := 'SELECT * FROM tblTest WHERE sysId = :sysId'; 
AdoQuery.Parameters.ParseSQL(ADOQuery.SQL.Text,True); 
AdoQuery.Parameters.ParamByName('sysId').value := -1; 
AdoQuery.open; 

ConnectionString (Datenbank: MyDb)

Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=MyDb;Data Source=. 

als Lösung ich dieses delphi code

AdoQuery.Parameters.ParseSQL(ADOQuery.SQL.Text,false); 

und kann nun jeder Körper diese Erklären verwenden? Gibt es irgendwelche Nebenwirkungen?

+0

Welche Version von SQL Server? Wie sieht der SQL-Code aus? Verwenden Sie mdac oder sqlncli, um eine Verbindung zur db herzustellen? –

+2

duplizieren ohne Antwort http://stackoverflow.com/questions/20813585/using-parsesql-command-for-ado-parameters-cause-invalid-parameter-datatype –

+0

@Mikael die Version ist sqlserver2008R2 und MDAC verwenden, um zu verbinden – imanShadabi

Antwort

3

Zunächst, bevor ich in irgendeine Erklärung über ParseSQL komme, überprüfen Sie Ihre Verbindungszeichenfolge. Zwischen Initial und Katalog gibt es zwei Leerzeichen. Als ich diese Verbindungszeichenfolge verwendete, kam es zu einem Fehler beim Öffnen der Abfrage, dass tblTest nicht existiert. Durch Entfernen des zusätzlichen Speicherplatzes wurde dieses Problem behoben.

Als ich diese Frage sah, hatte ich keine Ahnung was ParseSQL tut. Ich mache Delphi/SQL Server/ADO-Entwicklung seit Jahren und habe es nie benutzt. Ich dachte, dies wäre eine Gelegenheit, etwas Neues zu lernen.

Bitte beachten Sie, dass alle von mir durchgeführten Tests in Delphi 7 und Delphi XE5 zu identischen Ergebnissen führten. Ich wäre immer noch neugierig, etwas Code zu sehen, der in Delphi 7 funktioniert, aber in Delphi XE5 nicht funktioniert.

Wenn Sie AdoQuery.SQL.Text:='...' ausführen, erstellt die Anwendung die Parameter und fragt den Datenbankserver ab, um festzustellen, ob die Verbindung festgelegt und geöffnet ist. Dieser Code:

AdoQuery := tAdoQuery . Create(nil); 
AdoQuery . Connection := AdoConnection; 
ADOQuery.SQL.Text := 'SELECT * FROM tblTest WHERE sysId = :sysId'; 

aDataType := AdoQuery.Parameters.ParamByName ('sysId') . DataType; 
Msg ('Parameter type = ' + DataTypeToString (aDataType)); 

bewirkt:

Parameter type = ftInteger 

Hinweis, DataTypeToString ist nur eine Routine, die ich schrieb tDataType zu Zeichenfolge zu konvertieren.

function DataTypeToString (const nDataType : tDataType) : string; 
begin 
    Result := GetEnumName (TypeInfo(tDataType), 
          integer (nDataType)); 
end; 

Dann diesen Code ausführen.

AdoQuery.Parameters.ParamByName ('sysId') . Value := -1; 
AdoQuery . Open; 

Wenn Sie SQL Profiler ausgeführt werden Sie sehen, welche Abfrage an den SQL Server gesendet wird:

exec sp_executesql N'SELECT * FROM tblTest WHERE sysId = @P1 
',N'@P1 int',-1 

Beachten Sie, dass @ P1 als int deklariert wird.

Hinweis: Wenn in der Verbindungszeichenfolge zwei Leerzeichen enthalten sind, wird der Parametertyp als ftUnknown angezeigt, und @ P1 ist vom Typ smallint. Der Rest dieser Antwort wird davon ausgehen, dass Sie die richtige Verbindungszeichenfolge mit einem Leerzeichen haben.

Was macht das Rufen ParseSQL mit DoCreate=true?

AdoQuery.Parameters.ParseSQL(ADOQuery.SQL.Text,True); 

Das erste, was es tut, ist die Parameterliste zu löschen. In diesem Fall bedeutet das, dass der korrekt typisierte Parameter, den wir bereits hatten, zerstört wird. ParseSQL analysiert dann das SQL und findet den Parameter. Es erstellt ein neues tParameter Objekt mit dem Namen sysID und fügt es der Liste hinzu. Der neue Parameter hat den Typ ftUnknown.

Warum sollte jemand das tun wollen? Wenn die Abfrageverbindung NICHT festgelegt wurde oder nicht OPEN war, könnte dies sehr nützlich sein. Die Parameterliste wird für Sie erstellt, nach der Sie ihre Datentypen explizit festlegen können.

Was stattdessen, wenn Sie ParseSQL mit DoCreate=false auszuführen sind:

AdoQuery.Parameters.ParseSQL(ADOQuery.SQL.Text,false); 

Die Antwort ist: nichts. ParseSQL die SQL, findet die Parameter analysiert, und es wird eine Zeichenfolge wie folgt zurück:

SELECT * FROM tblTest WHERE sysId = ? 

ersetzt die Parameter mit einem Fragezeichen. Es werden keine Änderungen an der Parameterliste vorgenommen. Da Ihr Code nichts mit der zurückgegebenen Zeichenfolge ausführt, führt dies zu dem Ergebnis, dass dieser Aufruf von ParseSQL keine Änderungen vornimmt.