Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts (https://www.delphipraxis.net/149203-%5Bado-und-ms-sql-server-2005-2008%5D-ausfuehren-von-scripts.html)

tkoenig 16. Mär 2010 16:10

Datenbank: SQL Server • Version: 2005/2008 • Zugriff über: ADO

[ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Mahlzeit zusammen.

Ich habe ein Problem und bin langsam am verzweifeln, seit einer Woche durchforste ich jetzt schon das Internet, habe aber bisher keine zufriedenstellende Antwort zu meinem Problem gefunden.

Mein Problem ist folgendes:
Ich muss für ein Projekt (unter anderem) .sql-Dateien in mein Programm einlesen und diese an den SQL-Server übermitteln, der diese dann verarbeitet (Stichwort Query Analyzer). Die Scripts selbst können mehrere hundert Zeilen lang sein und sollten theoretisch keine Ergebnismenge zurückliefern.
Es soll ein Copy-Paste-Programm werden, deshalb benutze ich ADO um keine zusätzlichen Treiber oder Software wie die BDE etc. auf den Zielrechnern installieren zu müssen.

Ich verwende jetzt also eine TADOConnection-Komponente, Verbindung zum Server läuft super, einfache Scripts lassen sich auch ohne Fehler übertragen, allerdings kommt es bei größeren Transaktionen regelmäßig zu einer Exception á la "Syntaxfehler in der Nähe von "GO" / "Select" etc.". Scheinbar prüft also die ADOConnection die Syntax der Abfrage und blockiert diese unter Umständen. Ich weiß allerdings 100%ig, dass die SQL-Scripts korrekt sind, sie werden von Query Analyzer ohne Mucken verarbeitet.
Daher nun meine Frage: Kann ich der ADOConnection irgendwie mitteilen, dass ihr der Syntax meines Scripts egal zu sein hat?

Bis jetzt sieht der Code folgendermaßen aus:
Delphi-Quellcode:
function executeSQL(filename : string; ADO: TADOConnection) : boolean;
var i : integer;
    sql : widestring;
    success : boolean;
begin
  success := false;
  sql := CreateSQLSequence(filename);
  with ADO do
  begin
    if not Connected then Open;
    try
      BeginTrans;
      Execute(sql,i,[eoExecuteNoRecords]);
      success := true;
    except
      on e: Exception do
        success := false;
    end; // try .. except
    if success then
      CommitTrans
    else
    begin
      RollbackTrans;
      showmessage('Bei der Verarbeitung ist ein Fehler aufgetreten');
    end; // if .. else
    Close;
  end; // with ADO do
end; // executeSQL
Vielen Dank schonmal im Voraus für eure Hilfe.

Greetings, tkoenig

omata 17. Mär 2010 00:58

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Vielleicht so...
Delphi-Quellcode:
function executeSQL(filename : string; ADO: TADOConnection) : boolean;
var sql : widestring;
begin
  sql := CreateSQLSequence(filename);
  try
    if not ADO.Connected then
      ADO.Open;
    ADO.BeginTrans;
    ADO.Execute('execute(' + QuotedStr(sql) + ')');
    ADO.CommitTrans;
    ADO.Close;
    Result:=true;
  except
    on e: Exception do begin
      ADO.RollbackTrans;
      Result:=false;
      raise Exception.Create(
        'Bei der Verarbeitung ist folgender Fehler aufgetreten: ' + e.message
      );
    end;
  end;
end;

tkoenig 17. Mär 2010 08:06

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Erstmal danke für die Antwort, leider bleiben die Fehler die gleichen..

Meldung: Falsche Syntax in der Nähe von "GO". Die Syntaxprüfung ist also weiterhin aktiv...

Bbommel 17. Mär 2010 08:24

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Wie groß sind denn diese SQL-Dateien, bei denen das System anfängt rumzuzicken? Ich hatte vor einigen Tagen einen ähnlichen Effekt, allerdings nicht innerhalb von Delphi/ADO, sondern zunächst im Management Studio, aber dann auch beim etwas puristischeren "sqlcmd.exe". Ich hatte da SQL-Dateien, die so ~400 MB groß waren und die Fehlermeldungen, die da kamen, sahen deinen sehr ähnlich. Insofern wäre ich mir jetzt gar nicht mal so sicher, dass die ADO-Komponente die schuldige ist und eine Syntaxprüfung durchführt.

Ich hab es mir dann einfach gemacht und hab mir ein Programm geschrieben, das mir meine große SQL-Datei in viele kleine zerlegt hat, die ich dann nacheinander starte... dann geht es. Alternativ wäre mir in meinem Fall (in der Datei stehen sehr viele INSERTs) noch eingefallen, das alles selbst intern auszuwerten und "sauber" als Abfrage mit Parametern an den Server zu übertragen. Ersteres war dann aber der viel leichtere Weg.

Bis denn
Bommel

tkoenig 17. Mär 2010 08:35

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Zitat:

Zitat von tkoenig
Ich weiß allerdings 100%ig, dass die SQL-Scripts korrekt sind, sie werden von Query Analyzer ohne Mucken verarbeitet.

Das management Studio nimmt die Befehle wie gesagt ohne Probleme an, ist alles getestet. Meine Test-Datei ist dagegen eher klein (~10 KB), sehr viel größer werden die Dateien in Zukunft wohl auch nicht werden. Ich habe eher den Verdacht, dass ADO nicht mit mehreren Befehlen innerhalb einer Transaction klarkommt.

Die Option Datei selbst auswerten gefällt mir nicht so gut.. In einem 900 KB-Tool, das lediglich eine Datei an den Server sendet und ein paar andere Aufräumaufgaben übernimmt, wollte ich jetzt nicht unbedingt einen hochwertigen SQL-Parser einbauen, das würde den Rahmen dann doch sprengen ;)

MfG tkoenig

nahpets 17. Mär 2010 08:42

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Hallo,

die Syntaxprüfung dürfte von der Datenbank kommen.

Kann mir nicht vorstellen, dass die ADO-Connection für quasi jeden beliebigen Datenbanktyp vorab eine Syntaxprüfung durchführen kann.

Zumindest die Fehlermeldung Syntaxfehler in der Nähe von ist absolut typisch für den SQL-Server, die anderen, von mir bis dato genutzten Datenbanken, geben etwas präzisere Fehlermeldungen aus.

Dir bleibt hier (vermutlich) nichts anderes übrig, als Dir die Dateiinhalte zu nehmen und statementweise zu testen, d. h.:
zuerst das erste Statement, dann das erste und das zweite, dann das erste, das zweite und das dritte, bis Du das Script auf diese Weise wieder vollständig zusammengebaut hast, bzw. auf den ersten Fehler stößt.

Manchmal hilft zur Fehlerkorrektur ein zusätzliches Semikolon oder auch mal eins weglassen, eine zusätzliche Leerzeile zwischen einzelnen Statements...

Auch die Menge der Hochkommata sollte überprüft werden, zumindest, wenn sie irgendwo verschachtelt vorkommen.

Der Hinweis von Bommel ist nicht zu vernachlässigen: Kannst Du mit sql = widestring beliebig große Zeichenfolgen "übermitteln" oder gibt es da eine Grenze.
Lies zum Test Deine Dateien in sql ein und schreibe sql in eine neue Datei. Alte und neue Datei müssen identisch sein, wenn nicht, geht da was verloren und Du hast den "Übeltäter".

Unvollständige Statements passen sehr gut zu Deiner Fehlermeldung.

Kannst Du mit
Delphi-Quellcode:
Execute(sql,i,[eoExecuteNoRecords]);
beliebiggroße Statements übergeben oder hat diese Methode eventuell bezüglich der Größe der Zeichenfolge eine Begrenzung?

Auch Dein Hinweis
Zitat:

Ich habe eher den Verdacht, dass ADO nicht mit mehreren Befehlen innerhalb einer Transaction klarkommt
geht in die richtige Richtung, hierbei gilt die Einschränkung aber nicht in Bezug auf Transaktion sondern auf mehrere Befehle.

Es gibt Datenbanken, denen kann man per Query und ExecSQL mehrere Befehle "in einem Rutsch" übergeben, also Query.SQL enthält hier mehrere Befehle. Dies funktioniert allerdings nicht bei allen Datenbanken.

Für Deine eigentlich überschaubare Aufgabenstellung hast Du hier leider deutlich zuviele "Stolpersteine". Hoffe, Du findest mit unseren Hinweisen eine einfache Lösung.

Bbommel 17. Mär 2010 09:04

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Hm, okay, dann liegt der Fall wohl doch anders als bei mir. Spontan würde mir dann nur die etwas "eklige" Lösung einfallen, dass du über ein ShellExecute das "sqlcmd" mit der entsprechenden SQL-Datei aufrufst. Vielleicht klappt es ja dann ohne Fehler (kannst du ja auch erst mal "zu Fuß" testen).

Bis denn
Bommel

shmia 17. Mär 2010 14:14

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Dieses "GO" ist kein Befehl, der von der Treiberschicht ADO->OLEDB->SQL-Server verstanden wird.
Vermutung:
Die MS Tools wie Query Analyser, Enterprise Manager, SQL Server Management Studio sammeln die SQL-Befehle in einer Liste, bis "GO" angetroffen wird.
Dann wird die Liste der Befehle auf einen Rutsch an den SQL-Server gesendet.
Der Befehl "GO" selbst wird nicht gesendet.

tkoenig 17. Mär 2010 14:27

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Zu nahpets: Danke, dein Beitrag hat mir erstmal ein wenig zu denken gegeben, ich bin alles mal der Reihe nach durchgegangen.
Die Datei-Inhalte sequenzweise zu prüfen hat mich nicht weitergebracht. Sobald das erste GO auftritt (Zeile 2 :D), kommt selbige Fehlermeldung wieder. Wie gesagt, ich denke nicht, dass die sql-Datei Fehler entählt, da der Query-Analyzer des Management Studios alles ohne Fehler abarbeitet.

"sql" als Widestring hat bei mir die komplette Datei as is übernommen und auch komplett zurückgegeben, am widestring liegt es also auch nicht. Die Execute-Prozedur erwartet ebenfalls einen widestring als SQL-Befehl, daher gehe ich davon aus, dass eine Beschränkung auch darin nicht liegt.


Zu Bommel: Das ist eine gute Idee, aber leider nicht anwendbar, erstens aus Sicherheitsgründen, da das Passwort für den SQL-Server-Entwickleraccount (Adminrechte :zwinker: ) im Klartext an sqlcmd übergeben werden muss und zweitens weil dieses Programm auch von Clients auf einen SQL-Server im Netzwerk angewandt werden soll. Auf den Clients ist der SQL-Server und somit auch der sqlcmd-Dienst üblicherweise nicht installiert...


@shmia: Also bleibt mir nichts anderes übrig als einen Parser zu schreiben, der erstmal auf das Wort GO reagiert und die Datei dann sequentiell übermittelt? Oder sollte ich einen anderen Treiber als SQLOLEDB nehmen?


Greetings

Bbommel 17. Mär 2010 14:44

Re: [ADO und MS SQL-Server 2005/2008] Ausführen von Scripts
 
Hallo,

guter Hinweis von shmia. Dass "GO" kein gültiger T-SQL-Befehl ist steht auch im MSDN. :) Konsequenterweise wird dir also auch kein anderer Treiber weiterhelfen, weil der Server das "GO" schlicht nicht verarbeiten kann (es sei denn, du findest einen Treiber, der das dann wiederum selbst abfängt).

Letztlich wirst du wohl um ein bisschen Porgrammieren nicht drumrum kommen: Entweder du hast Glück und das "GO" ist eigentlich total überflüssig (hatte ich schon bei ein paar Fällen - ich muss zugeben, dass ich mich damals immer nur über die Fehler gewundert habe und erst jetzt durch deinen Thread auf die Ursache aufmerksam geworden bin), dann kannst du es ja einfach aus dem String rausschmeißen. Oder es ist nicht überflüssig, dann musst du halt den SQL-Befehl immer da, wo ein "GO" kommt, abschneiden und absenden. Ist aber doch eigentlich beides überschaubar. :)

Bis denn
Bommel


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz