Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server 2005 Fehler 701 – nicht genügend Arbeitsspeicher

Diese Frage scheint hier tatsächlich immer mal wieder aufzutauchen. Mark hat die richtige (und am häufigsten verwendete) Antwort, aber lassen Sie mich versuchen, hinzuzufügen, was ich kann, um dies klarer zu machen.

Die Fehlermeldung ist etwas irreführend. SQL Server teilt Ihnen mit, dass nicht genügend Arbeitsspeicher zum Ausführen vorhanden ist die Abfrage, aber was es wirklich bedeutet, ist, dass es nicht genug Speicher zum parsen hat die Abfrage.

Wenn es ums Laufen geht die Abfrage, kann SQL Server alles verwenden, was es will - Gigabyte, wenn nötig. Parsing ist eine andere Geschichte; der Server muss einen Parse-Baum aufbauen und dafür steht nur eine sehr begrenzte Menge an Speicher zur Verfügung. Ich habe das tatsächliche Limit nirgendwo dokumentiert gefunden, außer für einen typischen Stapel voller INSERT Anweisungen, kann es nicht mehr als ein paar MB gleichzeitig verarbeiten.

Es tut mir leid, Ihnen das zu sagen, aber Sie können nicht Lassen Sie SQL Server dieses Skript genau so ausführen, wie es geschrieben wurde. Auf keinen Fall, auf keinen Fall spielt es keine Rolle, welche Einstellungen Sie vornehmen. Sie haben jedoch eine Reihe von Optionen, um dies zu umgehen:

Konkret haben Sie drei Möglichkeiten:

  1. Verwenden Sie GO Aussagen. Dies wird von SSMS und verschiedenen anderen Tools als Batch-Separator verwendet. Anstelle eines einzelnen Analysebaums, der für das gesamte Skript generiert wird, werden einzelne Analysebäume für jedes Segment des Batches generiert, getrennt durch GO . Dies ist, was die meisten Leute tun, und es ist sehr einfach, das Skript dennoch transaktionssicher zu machen, wie andere demonstriert haben und ich werde es hier nicht wiederholen.

  2. Anstatt ein umfangreiches Skript zu generieren, um alle Zeilen einzufügen, speichern Sie die Daten in einer Textdatei (d. h. durch Kommas getrennt). Importieren Sie es dann mit dem bcp-Dienstprogramm . Wenn Sie möchten, dass dies "skriptfähig" ist - d.h. der Import muss im selben Skript/in derselben Transaktion wie CREATE TABLE erfolgen -Anweisung, und verwenden Sie dann BULK INSERT stattdessen. Obwohl BULK INSERT eine nicht protokollierte Operation ist, ob Sie es glauben oder nicht, sie kann immer noch innerhalb eines BEGIN TRAN platziert werden / COMMIT TRAN blockieren.

  3. Wenn Sie wirklich, wirklich das INSERT wollen ein protokollierter Vorgang sein soll und Sie nicht möchten, dass die Einfügungen stapelweise erfolgen, können Sie OPENROWSET um eine Textdatei, Excel-Datei etc. als Ad-hoc-"Tabelle" zu öffnen und diese dann in Ihre neu erstellte Tabelle einzufügen. Ich bin normalerweise abgeneigt, jemals die Verwendung von OPENROWSET zu empfehlen , aber da dies eindeutig ein Verwaltungsskript ist, ist es kein wirklich großes Problem.

Frühere Kommentare deuten darauf hin, dass Ihnen Nr. 1 unangenehm ist, obwohl dies möglicherweise nur an einer falschen Annahme liegt, dass dies nicht in einer einzigen Transaktion möglich ist. In diesem Fall siehe Thomas 's Antwort. Aber wenn Sie fest entschlossen sind, einen anderen Weg zu gehen, schlage ich vor, mit #2 weiterzumachen, eine Textdatei zu erstellen und BULK INSERT zu verwenden . Ein Beispiel für ein "sicheres" Skript wäre:

BEGIN TRAN

BEGIN TRY

    CREATE TABLE MyTable (...)

    BULK INSERT  MyTable
    FROM 'C:\Scripts\Data\MyTableData.txt' 
    WITH (
        FIELDTERMINATOR = ',',
        ROWTERMINATOR = '\r\n',
        BATCHSIZE = 1000,
        MAXERRORS = 1
    )

    COMMIT

END TRY

BEGIN CATCH

    ROLLBACK

END CATCH

Hoffentlich hilft dies, Sie auf den richtigen Weg zu bringen. Ich bin mir ziemlich sicher, dass dies alle verfügbaren "in-the-box"-Optionen abdeckt - darüber hinaus müssten Sie anfangen, tatsächliche Anwendungsprogramme oder Shell-Skripte zu schreiben, um die Arbeit zu erledigen, und ich glaube nicht, dass dies der Grad an Komplexität ist hier wirklich gerechtfertigt.