Als leidenschaftlicher Data Engineer und SSIS-Enthusiast habe ich schon unzählige Stunden damit verbracht, Execute SQL Tasks zu konfigurieren und mich über kryptische Fehlermeldungen zu ärgern. In diesem Blog-Post möchte ich meine Erfahrungen und Aha-Momente mit euch teilen: Warum funktioniert in OLE DB DECLARE @Var = ?
nicht, wie nutzt man stattdessen ADO .NET oder spielt geschickt mit Variablen und Dateiquellen? Gemeinsam werden wir die verschiedenen Verbindungstypen und SQLSourceTypes so durchleuchten, dass ihr künftig selbst die komplexesten SQL-Skripte in einem einzigen Task realisieren könnt – ohne lästige Workarounds oder zusätzlichen Overhead. Ich lade euch ein auf eine Reise durch die Welt des Parameter-Mappings, gespickt mit praxisnahen Tipps und echten Code-Beispielen, die euch im Alltag wirklich weiterhelfen. Viel Spaß beim Lesen und Nachbauen!
Einleitung
In SQL Server Integration Services (SSIS) werden über den Execute SQL Task oder Data-Flow-Quellen häufig Variablen an Abfragen übergeben, um dynamische SQL-Befehle zu realisieren. Dabei verhält sich die Parameter-Notation je nach Connection Manager (OLE DB, ADO, ADO .NET, ODBC, Excel) unterschiedlich, was oft zu Verwirrung und Fehlern führt. Dieser Artikel zeigt:
- Wie OLE DB-Verbindungen intern arbeiten und welche Einschränkungen sie bei Parametern haben [Microsoft Learn].
- Wie ADO und ADO .NET im Vergleich parametergesteuerte Abfragen handhaben [Microsoft Learn | Microsoft Learn].
- Dass ODBC und Excel ebenfalls das “?”-Marker-Verfahren verwenden [MaVa Analytics].
- Konkrete Workarounds und Praxisbeispiele, um komplexe Skripte dennoch in einem Task auszuführen.
SQLSourceType und SQLStatementSource
Die SQLSourceType-Eigenschaft im Execute SQL Task steuert, ob das SQL-Statement direkt eingegeben, aus einer Datei geladen oder aus einer Variablen gezogen wird. Während Direct Input und File Connection weitgehend erwartungsgemäß funktionieren, erlaubt Variable das Ausführen beliebig komplexer SQL-Strings, die zuvor in einer SSIS-Variable zusammengesetzt wurden – das gilt auch für OLE DB, allerdings ohne native Parameter-Unterstützung im String selbst. Das Parametermapping geschieht im gleichnamigen Tab des Execute SQL Task Editors und ordnet SSIS-Variablen den SQL-Parametern (positions- oder namensbasiert) zu.
Direct Input
Bei Direct Input wird das SQL direkt im Task-Editor unter SQLStatement hinterlegt. [Microsoft Learn] Diese Methode ist ideal für fixe, einfache Statements oder Stored-Procedure-Aufrufe mit ?
-Platzhaltern (OLE DB/ODBC) bzw. @Name
(ADO .NET). [Systems Engineering and RDBMS]
File Connection
Mit File Connection verweist der Task auf eine externe Datei (z. B. .sql
), die das Statement enthält. Ein File Connection Manager stellt den Zugriff sicher. [Microsoft Learn]Vorteil: SQL-Logik kann unabhängig vom Paketversioniert werden. Nachteile: Mehraufwand beim Deployment und bei Pfadänderungen.
Variable
Wählt man Variable, zieht der Task den gesamten SQL-Text aus einer SSIS-Variable (SourceVariable). [SQL Shack]So lassen sich dynamische oder sehr lange Skripte (inkl. DECLARE
, SET
, mehrere Batches) in einem Task ausführen, ohne Stored Procedures oder mehrere Tasks zu benötigen. [SQL Shack]OLE DB übernimmt den Text aus der Variable, führt ihn aus, kann jedoch keine ?
-Platzhalter innerhalb einer zusammengesetzten Variablen auflösen – Parameter müssen per String-Konkatenation oder späterem Mapping realisiert werden.
Parametermapping im Execute SQL Task
Im Execute SQL Task Editor gibt es einen Parameter Mapping-Tab, in dem SSIS-Variablen den SQL-Parametern zugeordnet werden. [red-gate.com]
Spalte Beschreibung Variable Name SSIS-Variable, die den Wert liefert oder aufnimmt Direction Input / Output / ReturnValue Data Type Datentyp der Variablen (VARCHAR, INT, etc.) Parameter Name Bei OLE DB/ODBC eine Positionsnummer (0,1,…), bei ADO .NET der benannte Parameter ( @Name
)Parameter Size Max. Länge (bei Strings)
- OLE DB/ODBC: Parameter Name = Index der
?
im SQL-Text. [Stack Overflow] - ADO .NET: Parameter Name = exakter Parameternamen im SQL (z. B.
@NameParam
). [MaVa Analytics] - Output und ReturnValue werden analog konfiguriert – nur der Direction-Typ ändert sich. [red-gate.com]
OLE DB
Hintergrundinformationen
OLE DB ist eine von Microsoft entwickelte Schnittstelle, die über COM-Objekte den Zugriff auf relationale und nicht-relationale Datenquellen ermöglicht. In SSIS liefert der OLE DB Connection Manager einen nativen Treiber für SQL Server sowie andere Datenbanken [Microsoft Learn].
- Vorteile: Hohe Performance, direkte Integration in Data-Flows, unterstützt Bulk-Operationen.
- Nachteile: Nur positionsbasierte Parameter (
?
), kein Support für benannte Parameter; keine komplexe SQL-Skripte mit internenDECLARE
-Bindungen möglich.
Parameterübergabe
Unter OLE DB werden Parameter über Platzhalter ?
im SQL-Text realisiert. Jeder ?
entspricht einem Eintrag in der Parameter Mapping-Liste, die nach Index (0, 1, 2 …) gegliedert ist [Stack Overflow].
-- Beispiel: zwei Parameter
SELECT *
FROM dbo.Tabelle
WHERE Spalte1 = ? -- Parameter0
AND Spalte2 = ?; -- Parameter1
EXEC dbo.usp_MeineProc ?, ?; -- Parameter 0 & 1
Ein DECLARE @var = ?
ist in OLE DB nicht möglich, da der Parser Parameter nur im reinen Command-Text erkennt und nicht innerhalb von DECLARE
oder SET
[Stack Overflow].
Rückgabewerte
Der Execute SQL Task für OLE DB unterscheidet drei Mechanismen:
- Input Parameters (
?
) - Output Parameters (z. B.
@par OUT
) - Return Value (z. B. Rückgabewert einer Stored Procedure) [sqlshack.com].
Für Output Parameters muss im Task der Parameter-Typ auf Output gesetzt und das SSIS-Variable-Mapping korrekt hinterlegt werden.
Output-Parameter (OUT
) und ReturnValue funktionieren ebenfalls mit ?
als Marker, erfordern aber das Setzen von Direction auf Output bzw. ReturnValue. [red-gate.com]
ADO
Der ADO Connection Manager (ActiveX Data Objects) ist der älteste SSIS-Connector und basiert auf COM; er wird heute meist nur noch für Legacy-Szenarien mit VB6-basierten Custom Tasks genutzt [Microsoft Learn | SQLServerCentral].
- Parametrierung: Verwendet wie OLE DB den
?
-Platzhalter, jedoch oft eingeschränkter SQL-Befehlssatz. - Use Case: Verbindung zu exotischen Datenquellen in älteren Infrastrukturen.
ADO.NET
Der ADO .NET Connection Manager nutzt die .NET Data Provider (z. B. SqlClient) und unterstützt benannte Parameter (@ParamName
) direkt im SQL-Text [Microsoft Learn | Microsoft Learn].
Hintergrundinformationen
ADO .NET (SqlClient) verwendet native .NET-Provider und benannte Parameter (@Param
). [MaVa Analytics]
- Vorteile: Benannte Parameter in
DECLARE
/SET
, bessere Unterstützung in Azure - Nachteile: Etwas mehr Overhead als OLE DB
Parameterübergabe & Mapping
-- 1. Variablen-Deklaration mit benannten Parametern
DECLARE @entityName VARCHAR(100) = @NameParam;
SET @entityName = REPLACE(@entityName, '_DELTA', '');
-- 2. Auslesen der GUID aus der Konfigurationstabelle
DECLARE @configGUID VARCHAR(100) = (
SELECT ConfigGUID
FROM [AppConfig].[ObjectMapping]
WHERE ObjectName = '[dbo].[' + @entityName + ']'
);
-- 3. Aufruf zweier Stored Procedures mit benannten Parametern
EXEC [dbo].[usp_CreateObjectView]
@ConfigGUID = @configGUID;
EXEC [dbo].[usp_UpdateObjectData]
@ConfigGUID = @configGUID,
@RunID = @RunID;

- Connection Manager: ADO.NET – SqlClient [Microsoft Learn]
- SQLSourceType: Direct Input (SQLStatement im Task-Editor) [Microsoft Learn]
Vorteile:
- Benannte Parameter, auch in komplexen Skripten mit
DECLARE
undSET
. - Bessere Integration mit SQL Azure (Active Directory-Authentifizierung).
- Rückgabewerte und Output Params analog zu ADO DB, aber benannt und typgesichert.
Warum ADO.NET hier ideal ist
- Benannte Parameter in
DECLARE
undSET
funktionieren sofort, ganz ohne Workarounds [SQL Shack]. - Ein Task, ein Skript: Alle Schritte – Deklaration, Select, SP-Aufrufe – bleiben lesbar und wartbar in einem Task [TECHCOMMUNITY.MICROSOFT.COM].
- Azure-freundlich: SqlClient-Provider ist das empfohlene Modell für Azure SQL und Hybrid-Workloads [Microsoft Learn].
Weiterführende Quellen
- Execute SQL Task – SQL Server Integration Services (SSIS) (Microsoft Docs) [Microsoft Learn]
- Execute SQL Task in SSIS: Output Parameters vs Result Sets (SQLShack) [SQL Shack]
- Execute SQL Task in SSIS (Mava Analytics) [MaVa Analytics]
- Passing Parameters using ADO.NET instead of OLEDB (TechCommunity) [TECHCOMMUNITY.MICROSOFT.COM]
- Accessing Stored Procedures using ADO.NET and Execute SQL Tasks (ClintonCherry) [Cherry Bytes]
ODBC
Der ODBC Connection Manager in SSIS verwendet ebenfalls ?
als Parameter-Marker [MaVa Analytics]. Technisch ist ODBC eine Standard-API, die über Treiberbrücken (z. B. SQL Server ODBC Driver
) auf die Datenquelle zugreift. Die Parametrisierung gleicht der von OLE DB, inklusive der Positionsabhängigkeit. [MaVa Analytics]
Excel
Der Excel Connection Manager nutzt eine OLE DB-ähnliche Engine für Excel-Dateien und unterstützt ebenfalls ?
-Platzhalter [MaVa Analytics].
- Einschränkungen: Begrenzte SQL-Dialect, keine Stored Procedures, Spaltennamen müssen in eckigen Klammern stehen (
[Spalte1] = ?
). [SQL Shack]
Praxisbeispiele
komplette SQL-Skripte
Im Alltag als SSIS-Entwickler stößt man immer wieder auf die gleiche Herausforderung: Man möchte komplexe, mehrstufige SQL-Skripte in einem einzigen Execute SQL Task abbilden – doch schon bei einfachen DECLARE
– und SET
-Anweisungen mit Parametern kommt der OLE DB Provider an seine Grenzen. Da steht man dann vor kryptischen Fehlermeldungen oder dem ungeliebten Workaround, den gesamten Code in Stored Procedures auszulagern. Genau hier setzt unser Kapitel an: Wir zeigen, wie du mit den Bordmitteln von SSIS – sei es über mehrere Tasks, über ADO .NET oder über das Variable-Mode–SQLSourceType – trotzdem komplette Skripte steuerst, Debugging überschaubar hältst und deine Package-Logik klar und wartbar gestaltest. Dabei gehe ich ganz konkret auf die Problematik ein, dass Platzhalter wie ?
in OLE DB nicht innerhalb von DECLARE
funktionieren, und gebe dir erprobte Strategien an die Hand, wie du dein dynamisches SQL dennoch sauber orchestrierst. Mit dieser Einführung wirst du verstehen, warum manche Ansätze scheitern und welche Werkzeuge dir wirklich helfen, dein Ziel in einem Task oder in minimalen Teilschritten zu erreichen.
Ausgangslage – Das Skript
-- 1. Variablen-Deklaration
DECLARE @entityName VARCHAR(100) = ?; -- Parameter 0
SET @entityName = REPLACE(@entityName,'_DELTA','');
-- 2. Auslesen der GUID aus einer Konfigurationstabelle
DECLARE @entityGUID VARCHAR(100) = (
SELECT EntityGUID
FROM [Config].[EntityMapping]
WHERE TableName = '[dbo].[' + @entityName + ']'
);
-- 3. Übergabe an zwei Stored Procedures
EXEC [dbo].[usp_GenerateEntityView]
@EntityGUID = @entityGUID;
EXEC [dbo].[usp_SynchronizeEntity]
@EntityGUID = @entityGUID,
@SessionID = ?; -- Parameter 1
Im obigen Skript siehst du zwei Stellen, an denen SSIS-Variablen als Parameter in das SQL eingebracht werden:
- Erster Parameter beim Initialisieren von
DECLARE @entityName VARCHAR(100) = ?;
- Hier übergibst du den Namen der Entität oder Tabelle, die das Paket gerade verarbeiten soll. So bleibt dein Package flexibel und du musst nicht für jeden neuen Tabellen- oder View-Namen den SQL-Text anpassen.
- Zweiter Parameter beim Aufruf der zweiten Stored Procedure
EXEC [dbo].[usp_SynchronizeEntity] @EntityGUID = @entityGUID, @SessionID = ?;
- Der
@SessionID
-Wert kann zum Beispiel eine Laufzeit-ID, ein Prozesskennzeichen oder eine Benutzer-Session abbilden, mit der du später in Logs oder Audit-Tabellen deine Ausführung eindeutig zuordnen kannst.
Typische Anwendungsfälle für solche Skripte
- Dynamische View-Erstellung
Automatisches Erzeugen von Sicht-Objekten auf Basis von Konfigurationstabellen, z. B. für mandantenabhängige oder rollenspezifische Datenzugriffe. - Konfigurationsgesteuerte ETL-Prozesse
Ziehen von Metadaten aus einer Mapping-Tabelle, um je nach Paketlauf verschiedene Datenquellen oder Zieltabellen anzusteuern. - Inkrementelle Synchronisation
Übergeben einer Sitzungs- oder Laufkennnummer (@SessionID
), um im Anschluss alle Änderungen dieser Session in eine Historie- oder Audit-Tabelle zu schreiben. - Archivierungs- und Löschjobs
Parametrisierte Stored Procedures, die per GUID oder Tabellennamen festlegen, welche Daten ein Archive- oder Cleanup-Prozess bewegen soll. - Mehrmandanten-Szenarien
Ein Paket für alle Mandanten, das über den ersten Parameter den Mandantenschlüssel übernimmt und so mandantenspezifische Datenpipelines steuert.
Durch diese Parametrisierung bleibt dein SSIS-Package sowohl wartungsfreundlich als auch wiederverwendbar für unterschiedlichste Szenarien – ganz ohne harte Codierung von Tabellennamen oder Session-IDs im SQL-Text.
Verwendung des kompletten Skripts im OLE DB
OLE DB unterstützt nur positionsbasierte Platzhalter ?
im reinen Command-Text, nicht aber innerhalb von DECLARE
oder SET
. Versuche wie
DECLARE @x VARCHAR(50) = ?;
werden vom OLE DB-Parser nicht erkannt und erzeugen Laufzeitfehler [Database Administrators Stack Exchange | Stack Overflow]
Workaround 1: Mehrere Execute SQL Tasks
Task 1
SELECT EntityGUID FROM [Config].[EntityMapping] WHERE TableName = ?;

- SQLSourceType = Direct Input
- ResultSet = Single row →
User::entityGUID
[red-gate.com]
Task 2
EXEC [dbo].[usp_GenerateEntityView] ?; EXEC [dbo].[usp_SynchronizeEntity] ?, ?;

So verteilst du dein Skript auf zwei Tasks und umgehst die OLE DB-Limitierung [red-gate.com].
Workaround 2: Stored Procedure
Auslagern des gesamten Skripts in eine Stored Procedure mit benannten Parametern.
Erstelle in der Datenbank eine SP, z. B.
CREATE PROCEDURE dbo.usp_ProcessEntity
@Name VARCHAR(100),
@SessionID VARCHAR(100)
AS
BEGIN
DECLARE @entityName VARCHAR(100) = @Name;
SET @entityName = REPLACE(@entityName,'_DELTA','');
DECLARE @guid VARCHAR(100) = (
SELECT EntityGUID
FROM [Config].[EntityMapping]
WHERE TableName = '[dbo].[' + @entityName + ']'
);
EXEC dbo.usp_GenerateEntityView @EntityGUID = @guid;
EXEC dbo.usp_SynchronizeEntity @EntityGUID = @guid, @SessionID = @SessionID;
END;
Im Execute SQL Task genügt dann:
EXEC dbo.usp_ProcessEntity ?, ?;

Dieser Ansatz ist besonders wartbar, wenn das SQL komplex ist oder von mehreren Packages genutzt wird [Microsoft Learn].
Workaround 3: Verwendung von Variablen
Im Execute SQL Task kannst du den kompletten SQL-Code in einer SSIS-Variable zusammenbauen und dann als SQLSourceType = Variable ausführen. Dadurch umgehst du die Einschränkung, dass OLE DB ?
-Platzhalter nur im reinen Command-Text erkennt, und kannst selbst komplexe Skripte mit DECLARE
, SET
und mehreren Batches in einem einzigen Task abbilden [SQL Shack | Stack Overflow].
Allgemein geht das so:
- Du erstellst eine String-Variable (z. B.
User::FullSqlCommand
), in der du über Expressions oder einen Script Task deinen kompletten SQL-Text dynamisch zusammensetzt. - Im Execute SQL Task setzt du SQLSourceType (bzw. SqlStatementSourceType) auf Variable und wählst deine
User::FullSqlCommand
als SourceVariable aus. - Der Task führt den Inhalt der Variable als SQL-Befehl aus – ganz gleich, ob es sich um OLE DB, ADO .NET oder ODBC handelt [SQL Shack | CData Software].
Vorteile dieser Methode
- Komplexität bündeln: Du brauchst keine mehreren Tasks und kein Lagern in Stored Procedures, da die gesamte Logik in der Variable liegt [Stack Overflow].
- Dynamische Parameter: Du kannst Werte direkt in den SQL-String einbetten (z. B. durch String-Konkatenation oder Expressions), statt sie als
?
oder benannte Parameter zu übergeben [Stack Overflow]. - Einheitlicher Task: Unabhängig von Connection Manager und dessen Parameter-Limitierungen führst du in einem Task aus – ideal für sehr lange oder sich häufig ändernde Skripte [SQLServerCentral].
Einschränkungen und Fallstricke
- SQL-Injection: Da du Werte als Literale in den String einfügst, musst du auf korrekte Escaping-Mechanismen achten, um Sicherheitslücken zu vermeiden [Stack Overflow].
- Debugging: Fehlermeldungen beziehen sich auf den generierten String – du musst den Inhalt der Variable vorher inspizieren, um Syntaxfehler zu finden [Microsoft Learn].
- Leistung: Sehr lange String-Konstruktionen können beim Parsen im Task zu Overhead führen; in manchen Fällen ist eine Stored Procedure performanter [Microsoft Learn].
Ein Task mit ADO.NET
Wähle im Execute SQL Task Connection = ADO .NET und nutze benannte Parameter:
DECLARE @entityName VARCHAR(100) = @NameParam;
SET @entityName = REPLACE(@entityName,'_DELTA','');
DECLARE @entityGUID VARCHAR(100) = (
SELECT EntityGUID
FROM [Config].[EntityMapping]
WHERE TableName = '[dbo].[' + @entityName + ']'
);
EXEC [dbo].[usp_GenerateEntityView] @EntityGUID = @entityGUID;
EXEC [dbo].[usp_SynchronizeEntity] @EntityGUID = @entityGUID,
@SessionID = @SessionID;

So fasst du alles in einem Task zusammen und nutzt die volle Flexibilität von ADO .NET [TECHCOMMUNITY.MICROSOFT.COM].
Fazit
- Mehrere Tasks (Workaround 1) bieten einfache OLE DB-Parameter, sind aber aufwändiger im Paket-Design.
- Stored Procedure (Workaround 2) verlagert Logik in die DB, ideal für Wartbarkeit und Wiederverwendung.
- ADO .NET (Workaround 3) ist die eleganteste Lösung für komplexes, batch-basiertes SQL in einem Task – wenn du den zusätzlichen Overhead und die .NET-Provider nutzen kannst.
Wähle je nach Szenario:
- Performance & Bulk-Loads → OLE DB mit mehreren Tasks
- Wiederverwendbarkeit & klare Trennung → Stored Procedure
- Dynamik & Komplexität in einem Task → ADO .NET.
Zusammenfassung
Zum Abschluss möchte ich noch einmal ganz personlig sagen: Ich weiß, wie frustrierend es sein kann, wenn ein scheinbar simpler DECLARE @Var = ?
-Befehl im OLE DB-Task nicht funktioniert und man vor kryptischen Fehlermeldungen steht. Deshalb habe ich dir hier einen Kompass an die Hand gegeben, mit dem du die verschiedenen Connection Manager (OLE DB, ADO, ADO .NET, ODBC, Excel) und ihre Eigenheiten beim Parametermapping souverän navigieren kannst.
Ich habe dir gezeigt, wie du in OLE DB mit mehreren Execute SQL Tasks saubere Zwischenschritte baust, wie du komplexe Logik in eine Stored Procedure auslagerst und – mein persönlicher Favorit – wie du per ADO .NET mit benannten Parametern alles in einem einzigen Task unterbringst. Und ja, manchmal ist es einfach am schnellsten, den gesamten SQL-Code in einer SSIS-Variable zusammenzubauen und als Variable-Quelle auszuführen – ein echter Geheimtipp, wenn’s mal schnell gehen muss.
Mein Ziel war es, dir nicht nur die technischen Fakten zu präsentieren, sondern auch die Gedanken und Erfahrungen, die dahinterstehen. Jetzt bist du bestens gerüstet, in deinem nächsten Projekt mühelos zwischen den Ansätzen zu wählen – je nachdem, ob du Performance, Wartbarkeit oder maximale Flexibilität brauchst. Viel Erfolg beim Umsetzen, und denk daran: Kein Workaround ist so gut wie das richtige Werkzeug für deine konkrete Aufgabe!
weiterführende Quellen
- Execute SQL Task – Parameter Mapping (Microsoft Docs)
- OLE DB Source – Parameter Use (Microsoft Docs)
- Execute SQL Task in SSIS: Output Params vs Result Sets (SQLShack)
- Parameterised OLE DB Source Query (StackOverflow)
- Passing Parameters with ADO.NET (TechCommunity)
- Connection Managers: OLE DB vs ODBC vs ADO .NET (SQLShack)
- Working with Variables in SSIS (Red-Gate)
- Arbitrary parameters in SSIS for OLE DB (CodeProject)
- Parameterized Execute SQL Task Examples (Mava Analytics)
- Passing a list to a SQL query in SSIS (DBA StackExchange)