zplCloud Blog
Lokalen SQL Server per zplCloud-CLI als Label-Datenquelle anbinden
Der Connection-String verlässt deine Maschine nie. Filter, Sortierung und Paging laufen als parametrisiertes T-SQL auf deinem Server.
Die Export-Schleife, und warum sie kaputtgeht
Labeldaten liegen im ERP, im WMS oder in einer Azure-SQL-Datenbank. Der übliche Ablauf: nach CSV exportieren, Spaltennamen geraderücken, hochladen, drucken - und morgen wieder, weil die CSV schon veraltet ist.
Der zplCloud-Datenhub schafft den Export ab. Ein CLI-Agent in deinem Netz hält den SQL-Server-Connection-String, die Plattform schickt ihm eine Abfragebeschreibung, und zurück kommen nur die Ergebniszeilen. Die Datenbank ist nie aus dem Internet erreichbar, die Zugangsdaten liegen nie in der Cloud.
Dieser Beitrag beschreibt die Mechanik: was wo läuft, welches SQL erzeugt wird und wo die harten Grenzen sind.
Architektur in einem Absatz
zplcloud proxy öffnet eine ausgehende TLS-Verbindung zu api.zplcloud.com (SignalR). Kein eingehender Port, keine NAT-Regel, kein VPN. Öffnest du in der Plattform eine Datenquelle, schickt das Backend dem Agent ein Request-Objekt - Basis-Query, Filter, Sortierung, Offset, Limit. Der Agent baut daraus T-SQL, führt es mit deinem Datenbankbenutzer aus und liefert die Zeilen zurück. Der Connection-String existiert nur im Prozess des Agents und in dessen lokaler Konfiguration.
Schritt 1 - Agent mit einem oder mehreren Servern starten
# Mehrere --sql-Flags sind erlaubt; der NAME ist das, was du später in der Plattform auswählst.
zplcloud proxy --agent "Lager" \
--sql PROD="Server=127.0.0.1;Database=erp;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True" \
--sql WAREHOUSE="Server=sql-wh.internal.lan,1433;Database=logistik;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True"
Dasselbe ohne Secrets in der Kommandozeile (die landen sonst in der Shell-History):
# Windows PowerShell - eine Variable je Server, der Name steht in der Mitte
$env:ZPLCLOUD_SQL_PROD_CONNECTION = "Server=127.0.0.1;Database=erp;User Id=zplcloud;Password=…;Encrypt=True;TrustServerCertificate=True"
zplcloud proxy --agent "Lager"
Der Startbanner listet, was gefunden wurde: SQL servers: PROD, WAREHOUSE. Die Authentifizierung gegenüber der Plattform läuft über --api-key <key> oder ZPLCLOUD_API_KEY.
Für den unbeaufsichtigten Betrieb dauerhaft ablegen:
- Windows:
setx ZPLCLOUD_SQL_PROD_CONNECTION "…"oderzplcloud proxy --agent "Lager" --service-install --api-key sk_zplcloud_… - Linux/Raspberry Pi: dasselbe
--service-install; es schreibt eine systemd-Unitzplcloud-agent.servicemitRestart=always - Datei statt Env:
sqlservers.jsonneben der Binary oder unter~/.zplcloud/, Aufbau{ "sqlServers": { "PROD": "Server=…" } } - Docker:
ZPLCLOUD_SQL_PROD_CONNECTIONindocker-compose.agent.yml
Connection-String-Details, die sonst eine Stunde kosten
Encrypt=True;TrustServerCertificate=Trueist das pragmatische Paar für einen internen Server mit selbstsigniertem Zertifikat.TrustServerCertificatefällt weg, sobald ein echtes Zertifikat da ist.- Eine benannte Instanz braucht
Server=host\\INSTANZ, ein abweichender PortServer=host,1433- Komma, kein Doppelpunkt. - Nimm einen eigenen SQL-Login mit
SELECTauf genau den Tabellen, die die Labels brauchen. Der Agent führt alles als dieser Benutzer aus - die Datenbank ist die Rechtegrenze, nicht die Plattform.
Schritt 2 - Datenquelle anlegen
Unter Datenquellen erscheint der laufende Agent als Remote SQL Server mit einem Chip je konfiguriertem Namen. Ein Klick auf den Chip füllt das Formular vor.
| Feld | Wert |
|---|---|
| Name | Lager-Artikel |
| Typ | SQL Server |
| Server | PROD (der Name aus --sql PROD=…) |
| Query | SELECT ean, name, price FROM artikel |
Test führt SELECT 1 aus und liefert server · datenbank. Felder liest die Spalten-Metadaten über SELECT TOP 1 * mit CommandBehavior.SchemaOnly - das Schema kommt, ohne Daten zu laden. Liefert eine stark verschachtelte Query kein Schema, versucht es der Agent einmal mit SingleRow.
Schritt 3 - was der Agent tatsächlich ausführt
Deine Basis-Query wird als Subquery gekapselt, Filter, Sortierung und Paging hängt der Agent an:
SELECT * FROM ( SELECT ean, name, price FROM artikel ) AS ds
WHERE ean LIKE @p0
ORDER BY name
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
Drei Punkte lohnen den zweiten Blick:
1. Werte sind Parameter, nie String-Verkettung. Der Filter-Builder erzeugt @p0, @p1, … und bindet die Werte über SqlCommand.Parameters. Es gibt keine Stelle, an der ein eingegebener Wert zu SQL-Text wird.
2. Paging ist nativ. limit 10 wird zu FETCH NEXT 10 ROWS ONLY; die Arbeit macht SQL Server, über die Leitung gehen zehn Zeilen - nicht eine Million.
3. Die Gesamtzahl ist eine eigene Abfrage. Wenn du den Total willst, läuft SELECT COUNT(*) FROM (<basis>) AS ds mit demselben WHERE und denselben Parametern.
Die harten Grenzen (aus dem Agent-Quellcode)
| Grenze | Wert | Gilt für |
|---|---|---|
| Zeilen pro Request | 1000 (RowCap) | limit wird auf 1…1000 begrenzt, Default ohne Angabe ist 100 |
| Command-Timeout | 15 s | Test, Describe, Query und Count |
| Statement-Typ | nur SELECT | die Basis-Query wird validiert, Multi-Statements werden abgelehnt |
| Sortier-/Filterspalten | validierte Bezeichner | werden nicht als freier SQL-Text durchgereicht |
Brauchst du mehr als 1000 Zeilen in einer Ansicht - Batch-Druck, ein ganzer Katalog - blättert die Plattform mit wachsendem OFFSET durch. Jede Seite ist ein eigener 1000-Zeilen-Request gegen deinen Server, der Speicherbedarf bleibt also konstant, egal wie groß das Gesamtergebnis ist.
15 Sekunden Timeout sind Absicht. Wenn deine Basis-Query nicht in 15 Sekunden antwortet, gehört sie in eine indizierte View oder eine Tabelle mit passendem Index - nicht in eine Label-Datenquelle.
Schritt 4 - im Designer und in Print Views nutzen
- Designer → Tab Testdaten → Datenquelle: Datenquelle wählen, Laden drücken. Die Feld-Bindings rendern mit echten Zeilen statt Platzhaltertext - du siehst die tatsächlichen Feldlängen, bevor irgendetwas beim Drucker landet.
- Print Views → Konfiguration → Datenquelle (Datenhub): Vorschau und Druck der View nutzen die Live-Query. Die Bedienung sieht aktuelle Daten, niemand lädt eine CSV neu hoch.
Fehlerbilder und was sie bedeuten
| Symptom | Ursache |
|---|---|
| Agent startet, aber kein Chip erscheint | --sql-Name fehlt, oder der Agent hat sich mit einem Key aus einem anderen Workspace angemeldet |
Test schlägt sofort fehl | Connection-String falsch (Instanz, Port, Zugangsdaten) - die Meldung kommt unverändert von SQL Server |
Test hängt und scheitert dann | 15-s-Timeout: Server vom Agent-Rechner aus nicht erreichbar, oder eine Firewall verwirft das Paket stillschweigend |
Felder liefert nichts | Basis-Query zu verschachtelt für SchemaOnly; der Fallback SingleRow braucht mindestens eine vorhandene Zeile |
| Query läuft, Print View bleibt leer | die View hängt an einer anderen Datenquelle, oder der Filter schließt alle Zeilen aus |
Tarif
Der Datenhub (SQL-Server- und MongoDB-Datenquellen über den CLI-Agent) gehört zum Pro-Tarif. Details auf der Preisseite.